本图书管理系统是基于Vue、Ajax、Node.js等技术的管理系统,笔者给其命名为阳光图书管理系统,意味着我们这个年纪应该活得洒脱像阳光一样,应充满活力与信心。再此感谢老师朋友的悉心指导,由于此系统是笔者初次完成的一个小型管理系统,必定有许多纰漏,如有不足请指正。
AJAX 是开发者的梦想,因为您能够:
不刷新页面更新网页
在页面加载后从服务器请求数据
在页面加载后从服务器接收数据
在后台向服务器发送数据
系统的具体实现过程,在此不再赘述,可以评论区留言将项目发送到您的邮箱。
系统开发完成之后,上线使用之前系统测试是必须的,因为只有对系统进行一个全面的测试,我们才可能发现系统中可能存在的问题,这些问题可能是技术缺陷,功能不全,业务需求达不到预先的效果等。新开发出来的系统没有十全十美的,所以这些缺陷有可能在测试中发现并得到解决,系统测试方法有很多,并且各个所占时间都不同,功能测试在整个系统测试的过程中占据的比例较大,功能测试也叫黑盒测试,黑盒测试不需要测试软件内部结构,目的是测试系统的功能。只要测试人员搭建好系统测试环境 。对各个函数接口进行测试即可。
硬件环境:笔记本或台式电脑
操作系统:Windows 10
软件环境: 谷歌浏览器、Microsoft Edge浏览器
只有严格按照完整的测试用例来对系统进行测试,才能使得系统不管是功能还是性能方面的质量都有所保证,没有十全十美的软件系统,但是我们可以通过测试减少很多不必要的错误,下面即是该系统的部分测试用例。
本次实验的设计与开发,是对本学期学习的一种很好的总结,在本学期的实验中,本次实验很具有挑战性,因此我选择了这个项目作为我的实验项目,在完成了实验的时候,我也遇到了许多困难与错误,在需求不明确的时候盲目的开发造成错误百出,某些知识点的掌握还不够,也有一些地方与预期不相符,我不得不查询各种资料,在一次次探讨之中,我慢慢的掌握的许多知识,在这些知识的认识之下,完成了该实验的设计与开发,技术与业务能力也有所提高,这对以后的事业发展有一定的积极影响作用
本次实验的开发与设计是在郭德先老师的指导下完成的,老师的建议和谆谆教诲使得实验在一点点的完善,在这一学期的学习中,正是老师的责任心引导着我们完成一次又一次的实验,每次遇到解决不了的问题时,都会向老师咨询,老师总是能给出合理的建议并不断鼓励我完成实验,再次由衷的感谢老师。
大家根据这个项目的目录结构搭建即可,如有疑问评论区私聊博主。想要搭建好的项目评论区留言邮箱。
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/vue@2">script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" />
<script src="https://unpkg.com/element-ui/lib/index.js">script>
<link rel="stylesheet" href="../css/index.css" />
<title>阳光图书馆title>
head>
<body>
<div id="logn" style="text-align: center">
<el-dialog
:visible.sync="dialogVisible"
style="width: 70%; text-align: center; position: absolute; left: 15%; top: 20%"
>
账号:<input type="text" v-model="temp_node.id" /> <br /><br />
密码:<input type="password" v-model="temp_node.name" /> <br /><br />
<el-button @click="dialogVisible = false">取 消el-button>
<el-button type="primary" @click="dialogVisible = false;dialogs();">确 定el-button>
el-dialog>
<el-dialog
:visible.sync="dialogVisible1"
style="width: 70%; text-align: center; position: absolute; left: 15%; top: 20%"
>
账号:<input type="text" v-model="temp_node.id" /> <br /><br />
年龄:<input type="text" v-model="temp_node.age" /> <br /><br />
<el-button @click="dialogVisible1 = false">取 消el-button>
<el-button type="primary" @click="dialogVisible1 = false;losepasswd();">确 定el-button>
el-dialog>
div>
<div class="back1" style="position: absolute">
<div class="namebgc">
<div class="head1">div>
<div class="headfont">
<div>阳div>
<div>光div>
<div>图div>
<div>书div>
<div>管div>
<div>div>
div>
div>
<div class="headtext">
<a href="#" class="button" onclick="vmadd()"> 登录 a>
<a href="resiger.html" class="button"> 注册 a>
<a href="#" class="button" onclick="vmlook()"> 找回密码 a>
<a href="#" class="button" onclick="vmdel()"> 注销账号 a>
div>
div>
<script>
function vmadd() {
vm.$data.dialogVisible = true
vm.$data.logordel = true
}
function vmdel() {
vm.$data.dialogVisible = true
vm.$data.logordel = false
}
function vmlook() {
vm.$data.dialogVisible1 = true
vm.$data.logordel = 3
}
let vm = new Vue({
el: '#logn',
data: {
userList: [],
dialogVisible: false,
dialogVisible1: false,
textvalue: '',
index: '',
temp_node: {
id: '',
age: '',
name: '',
},
logordel:0,
},
methods: {
//代码还是有点复杂:我们程序员还要手动完成数据组装
search() {
axios({
url: 'http://localhost:3000/users',
})
.then(function (response) {
vm.$data.userList = response.data
})
.catch(function (error) {
//失败
console.log(error)
console.log('===请求失败了===')
})
},
dialogs() {
if (this.$data.logordel) {
this.mlogin()
} else {
this.deluser()
}
this.resetTempNode();
},
// 登录函数
mlogin() {
for (let i = 0; i < this.userList.length; i++) {
if (this.userList[i].id == this.temp_node.id && this.userList[i].name == this.temp_node.name) {
alert('登录成功!')
// 前端小练习\阳光图书馆\html\opbook.html
// location.replace('D:/goStudy/前端大作业/前端小练习/opedata.html')
location.replace('opbook.html')
return
}
}
alert('未找到此用户!')
},
// 删除函数
deluser() {
for (let i = 0; i < this.userList.length; i++) {
if (this.userList[i].id == this.temp_node.id && this.userList[i].name == this.temp_node.name) {
axios({
method: 'DELETE', //删除
url: 'http://localhost:3000/users/' + this.temp_node.id, //id为"hello"
}).then(function (response) {
console.log(response.data)
})
alert('注销成功!')
this.search()
return
}
}
alert('未找到此用户!')
},
losepasswd(){
for (let i = 0; i < this.userList.length; i++) {
if (this.userList[i].id == this.temp_node.id && this.userList[i].age == this.temp_node.age) {
// console.log(this.userList[i].name)
alert("您的密码是:"+this.userList[i].name);
this.resetTempNode();
return
}
}
alert('您的信息有误!')
this.resetTempNode();
},
resetTempNode(){
this.temp_node.id = ''
this.temp_node.name = ''
this.temp_node.age = ''
}
},
created: function () {
this.search()
},
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/vue@2">script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" />
<script src="https://unpkg.com/element-ui/lib/index.js">script>
<title>操作图书title>
head>
<body>
<div id="app">
<el-container>
<el-header>
<el-menu class="el-menu-demo" mode="horizontal">
<el-menu-item index="1">处理中心el-menu-item>
<el-submenu index="2">
<temp_nodelate slot="title">我的工作台temp_nodelate>
<el-menu-item index="2-1">选项1el-menu-item>
<el-menu-item index="2-2">选项2el-menu-item>
<el-menu-item index="2-3">选项3el-menu-item>
<el-submenu index="2-4">
<temp_nodelate slot="title">选项4temp_nodelate>
<el-menu-item index="2-4-1">选项1el-menu-item>
<el-menu-item index="2-4-2">选项2el-menu-item>
<el-menu-item index="2-4-3">选项3el-menu-item>
el-submenu>
el-submenu>
<el-menu-item index="3" disabled>消息中心el-menu-item>
<el-menu-item index="4"><a href="https://www.ele.me" target="_blank">订单管理a>el-menu-item>
<el-menu-item index="4" style="position: absolute; right: 10%; background-color: aqua; color: black; border-radius: 40%">
<a href="index.html" style="text-decoration: none">退出登录a>
el-menu-item>
el-menu>
el-header>
<el-main >
<el-dialog
title="请输入您的信息!"
:visible.sync="dialogVisible"
style="width: 70%; text-align: center; position: absolute; left: 15%"
>
id:<input type="text" v-model="temp_node.id" /> <br /><br />
书名:<input type="text" v-model="temp_node.name" /> <br /><br />
作者:<input type="text" v-model="temp_node.author" /> <br /><br />
价格:<input type="text" v-model="temp_node.price" /> <br /><br />
<el-button @click="dialogVisible = false">取 消el-button>
<el-button type="primary" @click="dialogVisible = false;add_or_amend();">确 定el-button>
el-dialog>
<div id="app" class="mylist">
<el-card class="box-card" >
<el-table :data="bookList" style="width: 100%;">
<el-table-column prop="id" label="编号" width="%20">el-table-column>
<el-table-column prop="name" label="书名" width="%20">el-table-column>
<el-table-column prop="author" label="作者" width="%20">el-table-column>
<el-table-column prop="price" label="价格(元)" width="%20">el-table-column>
<el-table-column label="操作" width="%20">
<temp_nodelate slot-scope="scope">
<el-button
type="warning"
style="width: 30%"
v-on:click="addoramend=false;dialogVisible=true;index=scope.$index;"
>修改el-button
>
<el-button type="danger" style="width: 30%" v-on:click="index=scope.$index;del();">删除el-button>
temp_nodelate>
el-table-column>
el-table>
<div style="text-align: center">
<el-button style="width: 15%; margin-top: 1%" v-on:click="addoramend=true;dialogVisible=true"
>+el-button
>
div>
el-card>
div>
el-main>
<el-footer style="position: absolute; bottom: 20px; width: 100%">
<el-card>
<div style="text-align: center">
<el-link href="https://element.eleme.io" target="_blank">默认链接el-link>
<el-link type="primary">主要链接el-link>
<el-link type="success">成功链接el-link>
<el-link type="warning">警告链接el-link>
<el-link type="danger">危险链接el-link>
<el-link type="info">信息链接el-link>
div>
el-card>
el-footer>
el-container>
div>
<script>
// 创建一个vue对象
let vm = new Vue({
// 将这个vue对象与id为app的标签进行绑定
el: '#app',
// vue对象的数据库
data: {
// 存储所有书的列表
bookList: [],
dialogVisible: false,
textvalue: '',
sorttype: 0,
index: '',
temp_node: {
id: '',
name: '',
author: '',
price: '',
},
addoramend: true,
},
// vue对象的方法域
methods: {
//代码还是有点复杂:我们程序员还要手动完成数据组装
search() {
axios({
url: 'http://localhost:3000/book',
})
.then(function (response) {
vm.$data.bookList = response.data
})
.catch(function (error) {
//失败
console.log(error)
console.log('===请求失败了===')
})
},
// 删除
del() {
let aaa = this.bookList[this.index]
var mindex = this.index
let bbb = this.bookList.indexOf(aaa)
this.bookList.splice(bbb, 1)
axios({
method: 'DELETE', //删除
url: 'http://localhost:3000/book/' + aaa.id,
}).then(function (response) {
console.log(mindex)
})
},
// 修改
amend() {
let aaa = this.bookList[this.index]
let str = aaa.id
let bbb = this.bookList.indexOf(aaa)
for (let i = 0; i < this.bookList.length; i++) {
if (this.bookList[i].id == this.temp_node.id && i != bbb) {
alert('操作失败')
return
}
}
// 将新的属性给这个节点
this.bookList[bbb].id = this.temp_node.id
this.bookList[bbb].name = this.temp_node.name
this.bookList[bbb].author = this.temp_node.author
this.bookList[bbb].price = this.temp_node.price
// 先进行删除
axios({
method: 'DELETE', //删除
url: 'http://localhost:3000/book/' + str,
}).then(function (response) {
console.log(response.data)
})
// 再进行添加
axios({
method: 'POST', //增加
url: 'http://localhost:3000/book',
data: this.temp_node,
})
},
// 增加
add() {
// 判断一下表单是否为空
if (this.temp_node.id != '' && this.temp_node.age != '') {
let ma = { id: '', name: '', author: '', price: '' }
ma.id = this.temp_node.id
ma.name = this.temp_node.name
ma.author = this.temp_node.author
ma.price = this.temp_node.price
for (let i = 0; i < this.bookList.length; i++) {
if (this.bookList[i].id == ma.id) {
alert('该id已经存在!')
return
}
}
// 将新的节点加入页面
this.bookList.push(ma)
// 将新的节点添加到数据库
axios({
method: 'POST', //增加
url: 'http://localhost:3000/book',
data: ma,
})
.then(function (response) {})
.catch((err) => {
alert('操作失败')
})
}
},
// 判断是修改还是增加
add_or_amend() {
if (this.addoramend) {
this.add()
} else {
this.amend()
}
// 操作完后将表单数据置空
this.temp_node.id = ''
this.temp_node.author = ''
this.temp_node.name = ''
this.temp_node.price = ''
},
},
// 一个实例被创建之后执行的代码
created: function () {
this.search()
},
})
script>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/axios/dist/axios.min.js">script>
<script src="https://cdn.jsdelivr.net/npm/vue@2">script>
<link rel="stylesheet" href="../css/resiger.css">
<title>注册title>
head>
<body>
<div class="nav">
<form action="python">
<div style="color: steelblue;">
I    D: <input type="text" id="userid" class="texta"><br>
密    码: <input type="password" id="userpasd" class="texta"><br>
年    龄: <input type="text" id="userage" class="texta"><br>
<a type="button" class="mbuttom" href="#" onclick="resetvalue()">清空a>
<a type="button" class="mbuttom" href="#" onclick="submitvalue()">提交a>
<a type="button" class="mbuttom" href="index.html" style="width: 110px;">返回主菜单a>
div>
form>
div>
<script>
// 将临时节点的数据恢复初始值
function resetvalue(){
document.getElementById("userid").value="";
document.getElementById("userpasd").value="";
document.getElementById("userage").value=""
}
// 获取各个文本框的数据
function submitvalue(){
vm.$data.temp_node.id=document.getElementById("userid").value
vm.$data.temp_node.name=document.getElementById("userpasd").value
vm.$data.temp_node.age=document.getElementById("userage").value
vm.add()
}
let vm = new Vue({
el: '#app',
data: {
userList: [],
temp_node: {
id: '',
age: '',
name: '',
},
},
methods: {
search() {
axios({
url: 'http://localhost:3000/users',
})
.then(function (response) {
vm.$data.userList = response.data
})
.catch(function (error) {
//失败
console.log(error)
console.log('===请求失败了===')
})
},
// 增加
add(){
if(this.temp_node.id!=''&&this.temp_node.age!=''){
let ma={id:'',age:'',name:''};
ma.id=this.temp_node.id;
ma.age=this.temp_node.age;
ma.name=this.temp_node.name;
// 遍历用户列表进行查重
for(let i=0;i<this.userList.length;i++){
if(this.userList[i].id==ma.id){
alert('该id已经存在!请重新输入');
resetvalue();
return;
}
}
// 没有重复将数据插入列表内
this.userList.push(ma);
alert("注册成功!点击确定去登录")
resetvalue();
axios({
method:"POST",//增加
url:"http://localhost:3000/users",
data:ma,
}).then(function(response){
}).catch((err)=>{
alert('操作失败');
})
location.replace('index.html')
}
},
},
// 一个实例被创建之后执行的代码
created: function () {
this.search()
},
})
script>
body>
html>
/* 第一页背景 */
div {
display: inline-block;
}
a {
text-decoration: none;
}
/* body{
width: 100%;
} */
.back1 {
position: relative;
/* display: inline-block; */
width: 100%;
height: 1200px;
background: url('../imgs/image.png') no-repeat;
background-size: 100% 100%;
}
/* 网站简介 */
.namebgc {
position: absolute;
top: -20%;
width: 44%;
height: 16%;
background-color: transparent;
transform: translate(70%, 180%);
}
.head1 {
position: absolute;
margin-top: 23px;
margin-left: 39px;
width: 15.3%;
height: 65%;
background: url('../imgs/head1.png') no-repeat;
background-size: 100% 100%;
background-color: transparent;
/* transform: translate(10%,10%); */
transition: all 1s;
}
.head1:hover {
transform: rotate(360deg);
}
.headfont {
background-color: transparent;
width: 70%;
text-align: center;
margin-top: 20px;
margin-left: 20px;
position: absolute;
left: 180px;
font-size: 80px;
font-weight: 700;
transition: all 0.6s;
/* font-family: '幼圆'; */
}
/* 当鼠标经过图标时,有一定的动画效果 */
.headfont div:nth-child(1) {
transition: all 0.3s;
color: blueviolet;
}
.headfont div:nth-child(1):hover {
transform: translateY(-5px);
}
.headfont div:nth-child(2) {
transition: all 0.3s;
color: aqua;
}
.headfont div:nth-child(2):hover {
transform: translateY(-5px);
}
.headfont div:nth-child(3) {
transition: all 0.3s;
color: cornflowerblue;
}
.headfont div:nth-child(3):hover {
transform: translateY(-5px);
}
.headfont div:nth-child(4) {
transition: all 0.3s;
color: gold;
}
.headfont div:nth-child(4):hover {
transform: translateY(-5px);
}
.headfont div:nth-child(5) {
transition: all 0.3s;
color: tomato;
}
.headfont div:nth-child(5):hover {
transform: translateY(-5px);
}
/* 简介 1388*232 */
/* 放置登录、注册几个按钮的盒子 */
.headtext {
background-color: transparent;
position: absolute;
width: 40%;
height: 40%;
transform: translate(80%, 60%);
text-align: center;
font-size: 26px;
}
.headtext .button {
margin-left: 30%;
margin-top: 1%;
width: 40%;
height: 100px;
display: block;
border-radius: 30%;
border: cornflowerblue 5px solid;
font-size: 40px;
line-height: 100px;
color: lightblue;
transition: all 0.4s;
}
.headtext .button:hover {
transform-origin: center;
border-color: chartreuse;
color: chartreuse;
transform: scale(110%, 110%);
}
.nav{
display: inline-block;
width: 100%;
height: 780px;
text-align: center;
padding-top: 200px;
line-height: 30px;
background: url("../imgs/image.png") no-repeat;
background-size: 100% 100%;
font-size: 20px;
font-weight: 700;
}
.texta{
display: inline-block;
width: 400px;
height: 20px;
margin-top: 20px;
}
.mbuttom{
display: inline-block;
width: 60px;
height: 30px;
border-radius: 15px;
background-color: darkgray;
margin-left: 20px;
margin-right: 20px;
margin-top: 25px;
text-decoration: none;
color: rgb(85,39,140);
}
*{
margin: 0;
padding: 0;
}
本项目使用的是相对路径建好项目目录后直接将图片放在相应的目录即可
node.js
http://nodejs.cn/
element-ui
https://element.eleme.io/#/zh-CN
vue.js
https://cn.vuejs.org/index.html