个人介绍
专栏导航
文章目录
基于微信小程序的图书馆预约系统的设计与实现
1、前言介绍
2、开发技术简介
3、系统功能图
图书馆预约小程序提供了多项便捷的系统功能,以满足用户对图书馆资源的预约和管理需求。主要功能包括:
-
资源浏览:用户可以浏览图书馆的各类资源信息,包括图书、期刊、报纸等,了解资源的详细信息和可用性情况。
-
预约功能:用户可以通过小程序预约自己感兴趣的图书馆资源,选择借阅时间和地点,方便快捷。
-
个性化推荐:根据用户的借阅历史和兴趣偏好,系统会智能推荐相关的图书馆资源,提升用户体验。
-
预约管理:用户可以查看自己的预约记录、借阅历史等信息,方便管理自己的阅读计划。
-
消息通知:系统会及时向用户发送预约成功、借阅到期等消息通知,提醒用户注意借阅情况。
通过这些功能,用户可以方便地预约和管理图书馆资源,提升阅读效率和体验。
4、功能实现
系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。下图就是管理员登录页面。
5、库表设计
1.预约实体及其附属图
2.管理员实体及其附属图
6、性能测试
```java
1.from base.data_read import ReadData
2.from base.response import method_post
3.import pytest
4.# ====测试数据读取====
5.def data_read():
6. # 1. 将yaml文件读取
7. data_dict = ReadData('data.yaml').read_data()
8. # 2. 从字典中取数据 url accounts
9. url = data_dict['test_user_login']['url']
10. accounts = data_dict['test_user_login']['accounts']
11. # 3. 返回数据 供测试用例调用
12. return url, accounts
13.
14.
15.class TestLogin():
16. @pytest.mark.parametrize('url', [data_read()[0]])
17. @pytest.mark.parametrize('accounts', data_read()[1])
18. def test_login(self, url, accounts):
19. # 1. 注意这里的account是列表格式
20. print('\n>>>', type(accounts))
21. print(accounts)
22. # 2. 发请求
23. response = method_post(url, json=accounts)
24. # 3. 判断是否请求成功
25. assert response.status_code == 200
26. # 4. 根据返回的code判断是否登录成功
27. code = response.json().get('code')
28. print(response.json())
29. assert code == 0, '登录失败!'
30.# =============测试结果==============
31.========= 1 failed, 1 passed in 11.81s ==========
7、关键代码
<template>
<div>
<el-row>
<el-col :span="6">
<el-card style="height: 150px; margin: 10px; color: #67c23a">
<div>
<i class="el-icon-user-solid" style="margin-right: 10px"></i
>用户总数
</div>
<div style="margin: 30px 0; text-align: center; font-weight: bold">
{{ tableData.length }}
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card style="height: 150px; margin: 10px; color: #e6a23c">
<div>
<i class="el-icon-menu" style="margin-right: 10px"></i
>可预约座位总数
</div>
<div style="margin: 30px 0; text-align: center; font-weight: bold">
{{ labList.length }}
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card style="height: 150px; margin: 10px; color: #409eff">
<div>
<i class="el-icon-s-platform" style="margin-right: 10px"></i
>区域总数
</div>
<div style="margin: 30px 0; text-align: center; font-weight: bold">
{{ facilityList.length }}
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card style="height: 150px; margin: 10px; color: #f56c6c">
<div>
<i class="el-icon-s-comment" style="margin-right: 10px"></i>取消预约
</div>
<div style="margin: 30px 0; text-align: center; font-weight: bold">
{{ delectList.length }}
</div>
</el-card>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-card style="margin: 10px 10px; height: 400px">
<div
class="echarts2"
style="height: 350px; width: 500rpx"
ref="echarts2"
></div>
</el-card>
</el-col>
<el-col :span="12">
<el-card style="margin: 10px 10px; height: 400px">
<div
class="echarts1"
style="height: 350px; width: 500rpx"
ref="echarts1"
></div>
</el-card>
</el-col>
</el-row>
<router-view></router-view>
</div>
</template>
<script>
import { getAllReservation, getCancel } from "@/api/reservation";
import { allReservationTable } from "@/api/reservation";
import * as echarts from "echarts";
import { getUser } from "@/api/user";
import { getPlace, getSteat } from "@/api/index";
// import { getfk } from "@/api/sign";
const moment = require("moment");
export default {
data() {
return {
day: "",
tableData: [],
numList: [],
labList: [],
facilityList: [],
delectList: [],
tableName: {
username: "用户名",
phone: "手机号",
department: "院系",
},
};
},
components: {},
computed: {
tableData() {
return this.tableData.slice(0, 3);
},
},
methods: {},
mounted() {
//或群登录时间
let day = new Date();
this.day = `${day.getFullYear()}-${day.getMonth() + 1}-${day.getDate()}`;
// 代用封装的接口
getUser().then((res) => {
this.tableData = res.data.data.data;
});
getPlace().then((res) => {
this.facilityList = res.data.data.data;
});
getSteat().then((res) => {
let data = res.data.data.data;
let labList = [];
for (let i = 0; i < data.length; i++) {
if (data[i].status == 0) {
labList.push(data[i]);
}
}
this.labList = labList;
});
getAllReservation().then((res) => {
console.log(res.data.data.data);
let data = res.data.data.data;
// 使用reduce方法计算同一category的个数并添加到新的数组对象中
const resultArray = data.reduce((acc, curr) => {
const found = acc.find((item) => item.name === curr.placeName);
if (found) {
found.value++;
} else {
acc.push({ name: curr.placeName, value: 1 });
}
return acc;
}, []);
console.log(resultArray);
var echarts1 = echarts.init(this.$refs.echarts1);
var option = {
title: {
text: "图书馆预约概述",
subtext: "数据统计",
left: "center",
},
tooltip: {
trigger: "item",
},
legend: {
orient: "vertical",
left: "left",
},
series: [
{
name: "统计数据",
type: "pie",
radius: "50%",
data: resultArray,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
},
],
};
echarts1.setOption(option);
// 原始数组对象
});
//获取用户数据
getCancel().then((res) => {
let data = res.data.data.data;
this.delectList = data;
const resultArray = data.reduce((acc, curr) => {
acc.find((item) => item.name === curr.reason);
acc.push(curr.reason);
return acc;
}, []);
var newArr = resultArray.filter(function (item, index) {
return resultArray.indexOf(item) === index; // 因为indexOf 只能查找到第一个
});
console.log(newArr);
const resultArray1 = data.reduce((acc1, curr) => {
const found = acc1.find((item) => item.name === curr.reason);
if (found) {
found.value++;
} else {
acc1.push({ name: curr.reason, value: 1 });
}
return acc1;
}, []);
console.log(resultArray1);
let yData = [];
for (let i = 0; i < resultArray1.length; i++) {
let data = resultArray1[i].value;
yData.push(data);
}
var echarts2 = echarts.init(this.$refs.echarts2);
var option = {
title: {
text: "图书馆预约取消",
subtext: "数据统计",
left: "center",
},
xAxis: {
type: "category",
data: newArr,
},
yAxis: {
type: "value",
},
series: [
{
data: yData,
type: "line",
},
{
data: yData,
type: "bar",
},
],
};
echarts2.setOption(option);
});
},
};
</script>
<style lang="less">
.user {
display: flex;
align-items: center;
padding-bottom: 20px;
margin-bottom: 20px;
border-bottom: 1px solid #ccc;
img {
margin-right: 40px;
width: 150px;
height: 150px;
border-radius: 50%;
}
.userinfo {
p {
font-size: 32px;
}
}
}
.user-login {
p {
line-height: 28px;
font-size: 14px;
color: #999;
span {
color: #666;
margin-left: 60px;
}
}
}
.graph {
display: flex;
justify-content: space-between;
margin-top: 10px;
.el-card {
width: 48%;
}
}
</style>
<!--pages/index/index.wxml-->
<view class="banner">
<swiper class="swip_main" indicator-dots="true" autoplay='true' interval="3000" circular='true'>
<block wx:for="{{mglist}}">
<swiper-item>
<image style="width: 100%;height: 100%;" mode="aspectFill" src="{{item.imgUrl}}"></image>
</swiper-item>
</block>
</swiper>
</view>
<view class="body_yy">
<view class="body_yy_zz">自助约定</view>
<view class="body_yy_ms">安心学习,给你一个舒服的学习环境</view>
<button class="body_yy_bt" bindtap="my_yy">预定</button>
</view>
<view class="news-bar">
<view class="newa-bar-title">
图书馆公约
</view>
<view class="news-bar-box" wx:for="{{msgList}}" wx:for-item="item" wx:key="_id" bindtap="sjowbs" id="{{item.id}}" wx:if="{{index<10}}">
<view class="news-box-img">
<image src="{{item.imgUrl}}"></image>
</view>
<view class="news-box-text">
<view class="news-box-text-title">
{{item.title}}
</view>
<rich-text class="concent" nodes="{{item.concent}}"></rich-text>
<view class="news-bar-box-time">
{{item.uploadTime}}
</view>
</view>
</view>
</view>
8、源码获取
🎉写在最后
🍻伙伴们,如果你已经看到了这里,觉得这篇文章有帮助到你的话不妨点赞👍或 Star ✨支持一下哦!手动码字,如有错误,欢迎在评论区指正💬~
你的支持就是我更新的最大动力💪~