目录
一、前言介绍:
随着社会的进步,高校的扩招以及升学率的提高,高校学生人数急剧增长,宿舍 随着社会的进步,高校的扩招以及升学率的提高,高校学生人数急剧增长,宿舍需求也相应增长。学生宿舍管理系统是学校不可缺少的部分,它对于学校的决策者和管理者来说至关重要。大学四年甚至是更长时间我们都几乎在宿舍和亲密舍友度过,宿舍是学生在大学校园里一个非常重要的学习、生活、娱乐的地方,它是学生生活的港湾,在这里度过成长蜕变的光辉岁月。然而,传统的宿舍管理模式面对大量学生的住房需求也相应增长. 学生宿舍管理系统是学校不可缺少的部分,它对于学校的决策者和管理者来说至关重要.大学四年甚至是更长时间我们都几乎在宿舍和亲密舍友度过,宿舍是学生在大学校园里一个非常重要的学习、生活、娱乐的地方,它是学生生活的港湾,在这里度过成长蜕变的光辉岁月.然而,传统的宿舍管理模式面对大量学生的需求,宿舍的安全问题,信息的及时更新等弊端凸显,传统的宿舍管理过度的依靠人力资源的分配、登记,对于庞大的学生人数及学生信息,显然只依靠人力,很难准确的处理好大量的数据,传统的管理模式不仅效率低,出错率高,而且难查询宿舍及学生的实时信息,对于学校的管理带来了诸多不便,因此,能够开发一个大学生宿舍管理系统及时的了解到每个宿舍的住宿情况,人员信息,对于加强学校宿舍的安全管理,优化人力资源,合理调配新生入住,提高入住效率大有裨益。社会的科技进步,管理类软件系统的快速发展为解决这一难题提供了现实途径,学生宿舍的信息化管理方式以其方便、快捷、节省人力资源等优点成为解决这一问题的有效途径,用现代计算机技术对高校内住校学生的信息进行有效管理,快捷的处理大量数据,使得高校宿舍的信息化管理已成为必然的趋势。
二、主要技术:
1.后端框架Spring Boot介绍:
Spring框架是Java平台上的一种开源应用框架,提供具有控制反转特性的容器。尽管Spring框架自身对编程模型没有限制,但其在Java应用中的频繁使用让它备受青睐,以至于后来让它作为EJB(EnterpriseJavaBeans)模型的补充,甚至是替补。Spring框架为开发提供了一系列的解决方案,比如利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等等。Spring框架具有控制反转(IOC)特性,IOC旨在方便项目维护和测试,它提供了一种通过Java的反射机制对Java对象进行统一的配置和管理的方法。Spring框架利用容器管理对象的生命周期,容器可以通过扫描XML文件或类上特定Java注解来配置对象,开发者可以通过依赖查找或依赖注入来获得对象。Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。Spring框架的AOP框架仅提供基本的AOP特性,虽无法与AspectJ框架相比,但通过与AspectJ的集成,也可以满足基本需求。Spring框架下的事务管理、远程访问等功能均可以通过使用SpringAOP技术实现。Spring的事务管理框架为Java平台带来了一种抽象机制,使本地和全局事务以及嵌套事务能够与保存点一起工作,并且几乎可以在Java平台的任何环境中工作。
2.前端框架Vue介绍:
Vue是一款前端渐进式框架,可以提高前端开发效率。
- 渐进式意味着你可以将Vue作为你应用的一部分嵌入其中,带来更丰富的交互体验。
- 或者如果你希望将更多的业务逻辑使用Vue实现,那么Vue的核心库以及其生态系统。
- 比如Core+Vue-router+Vuex,也可以满足你各种各样的需求。
在此放上官网链接,可以自己进行查看学习:
https://cn.vuejs.org/https://cn.vuejs.org/
3.MYSQL数据库:
MySQL数据库使用的语言是SQL语言。MySQL在保存数据时是根据数据的类型和特征分开保存在不同的表中,这样当用户在需要调用的数据时,就不再需要花费大量时间去寻找数据了,只要找到对应的表,就可以找到需要的数据了。MySQL可以完美的实现对于数据库的基本操作。因为 MySQL 数据库的占用的内存少,运行快,成本低,源代码开放,可移植性强,所以越来越多的数据来源简单的项目的开发都会选择 MySQL作为数据库,而MySQL也变得越来越流行。
4.Axios:
1.Axios的介绍:
说到axios我们就不得不说下Ajax。在旧浏览器页面在向服务器请求数据时,因为返回的是整个页面的数据,页面都会强制刷新一下,这对于用户来讲并不是很友好。并且我们只是需要修改页面的部分数据,但是从服务器端发送的却是整个页面的数据,十分消耗网络资源。而我们只是需要修改页面的部分数据,也希望不刷新页面,因此异步网络请求就应运而生。
Ajax(Asynchronous JavaScript and XML):
异步网络请求。Ajax能够让页面无刷新的请求数据。
实现ajax的方式有多种,如jQuery封装的ajax,原生的XMLHttpRequest,以及axios。但各种方式都有利弊:
原生的XMLHttpRequest的配置和调用方式都很繁琐,实现异步请求十分麻烦
jQuery的ajax相对于原生的ajax是非常好用的,但是没有必要因为要用ajax异步网络请求而引用jQuery框架
Axios(ajax i/o system):
这不是一种新技术,本质上还是对原生XMLHttpRequest的封装,可用于浏览器和nodejs的HTTP客户端,只不过它是基于Promise的,符合最新的ES规范。具备以下特点:
在浏览器中创建XMLHttpRequest请求
在node.js中发送http请求
支持Promise API
拦截请求和响应
转换请求和响应数据
取消要求
自动转换JSON数据
客户端支持防止CSRF/XSRF(跨域请求伪造)
2.Axios的请求方式:
get:获取数据,请求指定的信息,返回实体对象
post:向指定资源提交数据(例如表单提交或文件上传)
put:更新数据,从客户端向服务器传送的数据取代指定的文档的内容
patch:更新数据,是对put方法的补充,用来对已知资源进行局部更新
delete:请求服务器删除指定的数据
三、功能截图:
1.登录、注册界面:
2.管理员权限界面:
3.普通用户权限界面:
4.个人信息界面:
用户在此界面可以进行信息查询和信息编辑
5.局部功能展示:
四、代码实现:
1.Axios的使用:
这里统一全局配置api
import axios from 'axios'
import router from "@/router";
import user from "@/views/User";
const request = axios.create({
baseURL: '/api', // 注意!! 这里是全局统一加上了 '/api' 前缀,也就是说所有接口都会加上'/api'前缀在,页面里面写接口的时候就不要加 '/api'了,否则会出现2个'/api',类似 '/api/api/user'这样的报错,切记!!!
timeout: 5000
})
// request 拦截器
// 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
config.headers['Content-Type'] = 'application/json;charset=utf-8';
//config.headers['token'] = user.token; // 设置请求头
let userJSON = sessionStorage.getItem("user")
if (!userJSON) {
router.push("/login")
}
return config
}, error => {
return Promise.reject(error)
});
// response 拦截器
// 可以在接口响应后统一处理结果
request.interceptors.response.use(
response => {
let res = response.data;
// 如果是返回的文件
if (response.config.responseType === 'blob') {
return res
}
// 兼容服务端返回的字符串数据
if (typeof res === 'string') {
res = res ? JSON.parse(res) : res
}
return res;
},
error => {
console.log('err' + error) // for debug
return Promise.reject(error)
}
)
export default request
2.跨域配置:
// 跨域配置
module.exports = {
devServer: { //记住,别写错了devServer//设置本地默认端口 选填
port: 9876,
proxy: { //设置代理,必须填
'/api': { //设置拦截器 拦截器格式 斜杠+拦截器名字,名字可以自己定
target: 'http://localhost:9090', //代理的目标地址
changeOrigin: true, //是否设置同源,输入是的
pathRewrite: { //路径重写
'^/api': '' //选择忽略拦截器里面的内容
}
}
}
}
}
3.登录验证码的设置:
<template>
<div class="ValidCode disabled-select"
:style="`width:${width}; height:${height}`"
@click="refreshCode">
<span v-for="(item, index) in codeList"
:key="index"
:style="getStyle(item)">
{{item.code}}
</span>
</div>
</template>
<script>
export default {
name: "ValidCode",
model: {
prop: 'value',
event: 'input'
},
props: {
width: {
type: String,
default: '100px'
},
height: {
type: String,
default: '34px'
},
length: {
type: Number,
default: 4
}
},
data () {
return {
codeList: []
}
},
mounted () {
this.createdCode()
},
methods: {
refreshCode () {
this.createdCode()
},
createdCode () {
const len = this.length
const codeList = []
const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789'
const charsLen = chars.length
// 生成
for (let i = 0; i < len; i++) {
const rgb = [Math.round(Math.random() * 220), Math.round(Math.random() * 240), Math.round(Math.random() * 200)]
codeList.push({
code: chars.charAt(Math.floor(Math.random() * charsLen)),
color: `rgb(${rgb})`,
fontSize: `1${[Math.floor(Math.random() * 10)]}px`,
padding: `${[Math.floor(Math.random() * 10)]}px`,
transform: `rotate(${Math.floor(Math.random() * 90) - Math.floor(Math.random() * 90)}deg)`
})
}
// 指向
this.codeList = codeList
// 将当前数据派发出去
this.$emit('input', codeList.map(item => item.code).join(''))
},
getStyle (data) {
return `color: ${data.color}; font-size: ${data.fontSize}; padding: ${data.padding}; transform: ${data.transform}`
}
}
}
</script>
<style scoped >
.ValidCode{
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
span{
display: inline-block;
}
}
</style>
4.登录界面Login.vue:
<template>
<div style="width: 100%; height: 100vh; overflow: hidden" class="login">
<div style="width: 350px; margin: 150px auto">
<div style="color: lightskyblue; font-size: 30px; text-align: center; padding: 30px 0">欢迎登录</div>
<el-form ref="form" :model="form" size="normal" :rules="rules">
<el-form-item prop="username" class="el-icon-user">
<el-input placeholder="账号" clearable v-model="form.username" />
</el-form-item>
<el-form-item prop="password">
<el-input placeholder="密码" v-model="form.password" show-password />
</el-form-item>
<ek-form-item>
<div style="display: flex">
<el-input v-model="form.validCode" style="width: 60%;" placeholder="请输入验证码"></el-input>
<ValidCode @input="createValidCode" />
</div>
</ek-form-item>
<el-form-item>
<el-button type="primary" style="width: 100%" @click="login" >登 录</el-button>
</el-form-item>
<el-form-item>
<el-button style="width: 100%" @click="register" >点击注册</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
import ValidCode from "@/components/ValidCode";
export default {
name: "Login",
components: {
ValidCode
},
data() {
return {
form: {role: 1},
rules: {
username: [
{required: true, message: '请输入用户名', trigger: 'blur'},
{min: 3, max: 10, message: "长度在3到10个字符", trigger: "blur"},
],
password: [
{required: true, message: '请输入密码', trigger: 'blur'},
{ type: 'string', message: '请输入不包含空格的字符', trigger: 'blur', transform(value) {
if (value && value.indexOf(' ') === -1) {
return value
} else {
return false
}
}
},
{ trigger: 'blur', validator: (rule, value, callback) => {
var passwordreg = /(?=.*\d)(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{6,10}/
if (!passwordreg.test(value)) {
callback(new Error('密码必须由数字、字母、特殊字符组合,请输入6-10位'))
}else{
callback()
}
} }
],
},
validCode: '',
}
},
created() {
sessionStorage.removeItem("user")
},
methods: {
register:function(){
this.$router.push({
name:'Register'
});
},
//接收验证码组件提交的4位验证码
createValidCode(data) {
this.validCode = data
},
login() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (!this.form.validCode) {
this.$message.error("请填写验证码")
return
}
if (this.form.validCode.toLowerCase() !== this.validCode.toLowerCase()) {
this.$message.error("验证码错误")
return
}
request.post("/user/login", this.form).then(res => {
if (res.code === '0'){
this.$message({
type: "success",
message: "登录成功"
})
sessionStorage.setItem("user", JSON.stringify(res.data))//缓存用户信息
this.$router.push("/index") //登录成功过后进行页面跳转到主页
} else {
this.$message({
type: "error",
message: res.msg
})
}
})
}
});
},
}
}
</script>
<style scoped >
.login {
height: 100%;
font-family: JetBrains Mono Medium;
display: flex;
align-items: center;
justify-content: center;
background-color: white;
background-size: 100% 100%;
}
</style>
5.用户控制层Contorller:
package com.example.demo.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@ResponseBody
@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
UserMapper userMapper;
@PostMapping("/login")
public Result<?> login(@RequestBody User user){
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery()
.eq(User::getUsername, user.getUsername())
.eq(User::getPassword, user.getPassword()));
if (res == null) {
return Result.error("-1", "用户名或密码错误");
}
return Result.success(res);
}
@PostMapping("/register")
public Result<?> register(@RequestBody User user){
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery()
.eq(User::getUsername, user.getUsername()));
if (res != null) {
return Result.error("-1", "用户名重复");
}
if (user.getPassword() == null){
user.setPassword("654321");
}
userMapper.insert(user);
return Result.success();
}
@PostMapping
public Result<?> save(@RequestBody User user){
if (user.getPassword() == null){
user.setPassword("123456");
}
userMapper.insert(user);
return Result.success();
}
@PutMapping
public Result<?> update(@RequestBody User user){
userMapper.updateById(user);
return Result.success();
}
@DeleteMapping("/{id}")
public Result<?> delete(@PathVariable long id){
userMapper.deleteById(id);
return Result.success();
}
@GetMapping("/{id}")
public Result<?> getById(@PathVariable long id){
return Result.success(userMapper.selectById(id));
}
@GetMapping
public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(defaultValue = "") String search) {
LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery();
if (StrUtil.isNotBlank(search)) {
wrapper.like(User::getNickName, search);
}
Page<User> userPage = userMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
return Result.success(userPage);
}
}
6.头部Header:
<template>
<div style="height: 50px; line-height: 50px; border-bottom: 1px solid #ccc; display: flex">
<div style="width: 200px; padding-left: 20px; font-weight: bold; color: black">宿舍管理系统</div>
<div style="flex: 1"></div>
<div style="width: 100px; padding-top: 16px">
<el-dropdown>
<span class="el-dropdown-link">
{{user?.nickName}}
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
@click="$router.push('/person')">
个人信息</el-dropdown-item>
<el-dropdown-item
@click="$router.push('/login')">
退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</template>
<script>
export default {
name: "Header",
props: ["user"],
data() {
return {
user: {}
}
},
created() {
let userStr = sessionStorage.getItem("user") || "{}"
this.user = JSON.parse(userStr)
},
}
</script>
<style scoped>
</style>
五、结论:
对于本次的系统开发来看,它主要是把我以前所学的知识进行了一次综合的应用。经过这次毕业设计的制作它主要是把我以前所学的理论知识应用到社会实践当中。通过这一次的点餐平台网站的设计与实现它能够有效把计算机知识与实际问题相互应用,通过计算机网络技术来解决用户生活当中的实际问题,从而提高我的编程能力。虽然在这次毕业设计当中我遇到了很多的问题和困难,但是通过不断的调试和老师的帮助让我圆满的完成了这次毕业设计。通过这次毕业设计的制作让我对计算机实际应用得到了很强的锻炼,同时也大大的提高了我的动手动脑能力,让我也感受到了其中的乐趣和喜悦。通过这次毕业设计的撰写把我在大学期间所学到的东西都应用上了,但是我觉得还是微不足道的,因为在这次毕业设计当中让我深深的了解到对于软件开发和学习理论知识它是两个完全不同的概念。但是通过这次软件的开发让我在以后的工作当中打下了良好的基础。
六、源码获取:
大家点赞,收藏,评论啦!如有需要可以私信我,我在看见信息的第一时间会进行回复。