高校宿舍管理系统

2023-10-26

高校宿舍管理系统

项目截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.项目概况

​ 提到宿舍,现在无论是学校,还是工厂,都是在熟悉不过的了,学生宿舍楼,职工教员工,职工宿舍楼等等,每一栋楼房都有很多的房间,每个宿舍分配了多少个床位,住着什么人,那些床位是空的,那些房间是空的,这些都需要人员去维护,曾经的我们,通过纸张登记,查看房间信息,房间床位信息,房间少的情况下还好,我们可以一个个进行比对,看登记信息去查看房间信息,床位信息,但是房间多,登记信息多的情况下,或者有人员进行变动,退房,换房的情况下,可就麻烦了我们的宿舍管理员了,我们的宿舍管理员,需要慢慢的进行查找,浪费了时间成本不说,还容易出错,新来的学生或员工需要等待很长时间才能进去入住,在加上现在楼层在逐渐的向高层发展,人员手动管理已经不能满足社会的需要,因而,社会需要更好的工具去管理这些枯燥的的宿舍管理工作,从而宿舍管理系统应用而生。

​ 宿舍管理系统,解决了当前人力成本,时间成本问题,可以快速的定位到房间号,宿舍床位号,通过宿舍管理系统,我们只要根据系统的要求去操作,就可以分分钟的时间解决某个宿舍是否满员,可以方便的把人员和宿舍,床位进行绑定,就像我们的身份号似的,都是唯一的,查询起来很方便,相比较起传统的宿舍纸张登记来说,现代化的宿舍管理系统更快捷,更高效,更适应人们快捷化的生活。

​ 现在高校的发展和体制不断的进行了完善,所以学校的服务也逐渐有了变化,对于学校宿舍的管理有了新形势的管理模式。学校根据自身的实际情况,对于学生宿舍生活管理的服务进行改善。有些学校因为管理工作的错误,影响了学校里学生的现况,甚至给整个学校造成了负面的影响,而且现在学校管理问题普遍存在。所以现在学校也在建设信息化管理系统,这种管理系统,可以为学校的管理工作和宿舍管理工作带来很好的效果。

2.项目目标

2.1新生分配与入住

在高校新生入住和分配上面,宿舍管理系统优势尽显,通常宿舍管理系统可通过新生预分配和新生入住两个模块实现对新生宿舍入住和宿舍分配的管理,这不但可保证分配入住的科学性,还能提升学生的入住效率,既减轻了人工分配的负担,也简化了学生的入住手续,更好地促进了学校和新生之间的和谐。

2.2宿舍的全面管理

通过对宿舍管理系统进行优化,高校宿舍的管理工作可细化成若干个系统的小模块,宿舍管理工作的细化在利于学生便捷高校入住的同时还让高校宿舍管理的智能化和信息化得到了进一步的彰显,通过对宿舍管理系统的全面优化,从整栋宿舍楼的整体管理到每一个床位的每一个角落都会实现整齐划一的管理。

楼->单元->层->宿舍->床位

2.3数据科学统计和分析

宿舍管理系统中记载着整栋宿舍楼的和全部入住学生的相关信息,通过其完善智能的信息统计功能,高校或者宿舍管理者可对每个楼层的入住情况、每个房间的入住信息数据实现一键查看,不用再通过一步步、一级级地层层询问来获取相关信息,这在很大程度上促进了宿舍信息的共享。

2.4精细化管理

宿舍考勤,管理员,多角色管理,一目了然。寄宿生管理,班级,楼层、宿舍号精确考勤。床位分配管理,楼、栋管理员都有相对应的权限。就寝时间段可设置,班主班可随时关注住宿学生情况及时报表发送至班主任手机。

2.5接口拓展功能

系统预留的接口可与宿舍其他的智能设施实现对接,如宿舍管理系统可连接宿舍的考勤门禁系统和迎新收费系统,可真正通过计算机管理系统的运用实现智能化校园的建设。

3.项目功能

3.1 项目角色(参与者)
  • 超级管理员(拥有系统最高的权限)

  • 宿管员(宿舍管理员:对宿舍进行管理,按楼宇进行管理)

  • 学生(在线预选宿舍)

    详见思维导图(xmind文件 )

3.1 项目功能
  • 基础资料
    • 用户管理(管理员、宿管员管理)
    • 年级管理
    • 学院、系、专业、班级(统称为组织机构)
    • 学生管理
    • 公告管理
  • 宿舍管理
    • 楼宇管理
    • 楼层管理
    • 宿舍管理(批量初始化、CURD)
    • 床位管理(入住、调换、退宿)
  • 预选宿舍
    • 预选设置
    • 预选操作
  • 缺勤、请假管理
    • 缺勤登记(影响床位状态)
    • 请假登记(影响床位状态)
  • 来访人员管理
    • 登记来访信息
    • 查询来访信息
  • 报修管理
    • 报修申请
    • 状态审批
    • 报修查询
  • 报表/图表管理
    • excel报表
    • echarts图表显示

4.数据库设计

数据库设计软件PowerDesigner

安装:百度一下PowerDesigner的安装教程

PowerDesigner与Navicate的区别

  • PowerDesigner重在可视化的设计
  • Navicate就是一个数据库的可视化客户端工具

详见pdm图

5.项目技术路线

后端采用SpringBoot

前端采用LayUI(在开发前端期间不涉及任何前后端页面跳转,只通过json数据传输,前后数据校验采用JWT)

数据库采用MySQL(5.5至8.0)

开发IDE:Idea、webstorme

请求校验:JWT

该项目支持三个版本

  • 前后端分离(SpringBoot+LayUI)(前后端来回切换台费劲,容易混淆)
  • SpringBoot版本前后端不分离(快速开发调试)
  • SSM版前后端不分离(需要将SpringBoot的配置重新按照xml的 格式配置一遍)

6.项目搭建

<mirror> 
    <id>alimaven</id> 
    <name>aliyun maven</name> 
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url> 
    <mirrorOf>central</mirrorOf> 
</mirror>
  • public:静态html文件

  • static:静态css、js等文件

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/dormitory?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
    username: root
    password: 123456
server:
  port: 8888
  servlet:
    context-path: /dormitory

7.整合Mybatis

在pom.xml中引入starter

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
</dependency>
配置Mapper目录
mybatis:
  mapper-locations: com/yanzhen/mapper/*.xml
打印SQL输出到控制台
logging:
  level:
    com:
      yanzhen:
        mapper: debug

8.Mybatis分页

引入相关的jar

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>

配置yml文件

pagehelper:
  helper-dialect: mysql
public class Entity {

    private Integer page;//页码数
    private Integer limit = 10;//页面大小,默认的10

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Integer getLimit() {
        return limit;
    }

    public void setLimit(Integer limit) {
        this.limit = limit;
    }

}

9.代码生成器

entity

package ${data.packageName}modules.${data.moduleName}.entity;

import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Length;
import com.yanzhen.utils.Entity;
import java.util.Date;


/**
 * ${data.classAnnotation}
 * @author ${data.author}
 * @time ${data.createTime}
 */
public class ${data.entityName} extends Entity{

<#list data.datas as item>
	/**
	 * ${item.annotation}
	 */
	<#if item.type == "String" && item.field !="id">
	@Length(max = ${item.typeLength?c})
	</#if>
	private ${item.type} ${item.field};
</#list>

<#list data.datas as item>
	public ${item.type} get${item.fieldUpper}() {
		return ${item.field};
	}
	public void set${item.fieldUpper}(${item.type} ${item.field}) {
		this.${item.field} = ${item.field};
	}
</#list>
}

mapper

package ${data.packageName}.mapper;

import java.util.List;
import java.util.Map;

import ${data.packageName}.entity.${data.entityName};

public interface ${data.entityName}Mapper {

	public int create(${data.entityName} ${data.objectName});

	public int delete(Integer id);

	public int update(${data.entityName} ${data.objectName});

	public int updateSelective(${data.entityName} ${data.objectName});

	public List<${data.entityName}> query(${data.entityName} ${data.objectName});

	public ${data.entityName} detail(Integer id);

	public int count(${data.entityName} ${data.objectName});

}

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${data.packageName}.mapper.${data.entityName}Mapper">

	<resultMap type="${data.packageName}.entity.${data.entityName}" id="${data.entityName}">
		<id column="id" property="id"/>
		<#list data.datas as item>
		<#if item.column == "id"><#continue></#if>
		<result column="${item.column}"  property="${item.field}"/>
		</#list>
	</resultMap>

	<insert id="create" keyProperty="id" useGeneratedKeys="true" parameterType="${data.packageName}.entity.${data.entityName}">
		insert into ${data.tableName}(
		<#list data.datas as item>
			<#if item.column == "id"><#continue></#if>
			${item.column}<#if item_index!=(data.datas?size-1)>,</#if>
		</#list>
		)values(
		<#list data.datas as item>
			<#if item.column == "id"><#continue></#if>
			<#noparse>#{</#noparse>${item.field}<#noparse>}</#noparse><#if item_index!=(data.datas?size-1)>,</#if>
		</#list>
		)
	</insert>

	<select id="query" resultMap="${data.entityName}">
		select * from ${data.tableName}
		<include refid="${data.entityName}FindCriteria"/>
	</select>

	<select id="count" resultType="int">
		select count(1) from ${data.tableName}
		<include refid="${data.entityName}FindCriteria"/>
	</select>

	<select id="detail" resultMap="${data.entityName}">
		select * from ${data.tableName} where id = <#noparse>#{id}</#noparse>
	</select>

	<delete id="delete">
		delete from ${data.tableName} where id = <#noparse>#{id}</#noparse>
	</delete>
	<update id="update">
		update ${data.tableName} set
		<#list data.datas as item>
			<#if item.column == "id"><#continue></#if>
			${item.column}=<#noparse>#{</#noparse>${item.field}<#noparse>}</#noparse><#if item_index!=(data.datas?size-1)>,</#if>
		</#list>
		where id = <#noparse>#{id}</#noparse>
	</update>

	<update id="updateSelective">
		update ${data.tableName} set
		<#list data.datas as item>
		<#if item.column == "id"><#continue></#if>
		<#if item.type == "String" || item.type == "Date">
			<if test="${item.field} != null and ${item.field} != ''"> ${item.column} = <#noparse>#{</#noparse>${item.field}<#noparse>}</#noparse></if><#if item_index!=(data.datas?size-1)>,</#if>
		<#else>
			<if test="${item.field} != null">${item.column} = <#noparse>#{</#noparse>${item.field}<#noparse>}</#noparse></if><#if item_index!=(data.datas?size-1)>,</#if>
		</#if>
		</#list>
		where id = <#noparse>#{id}</#noparse>
	</update>

	<sql id="${data.entityName}FindCriteria">
		<where>
		<#list data.datas as item><#if item.type == "Date"><#continue></#if>
		<#if item.type == "String">
			<if test="${item.field} != null and ${item.field} != ''">and ${item.column} = <#noparse>#{</#noparse>${item.field}<#noparse>}</#noparse></if>
		<#else>
			<if test="${item.field} != null">and ${item.column} = <#noparse>#{</#noparse>${item.field}<#noparse>}</#noparse></if>
		</#if>
		</#list>
		</where>
	</sql>

</mapper>

service

package ${data.packageName}.service;

import com.yanzhen.mapper.${data.entityName}Mapper;
import com.yanzhen.entity.${data.entityName};
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ${data.entityName}Service {

    @Autowired
    private ${data.entityName}Mapper ${data.objectName}Mapper;

    public int create(${data.entityName} ${data.objectName}) {
        return ${data.objectName}Mapper.create(${data.objectName});
    }

    public int delete(Integer id) {
        return ${data.objectName}Mapper.delete(id);
    }

    public int update(${data.entityName} ${data.objectName}) {
        return ${data.objectName}Mapper.update(${data.objectName});
    }

    public int updateSelective(${data.entityName} ${data.objectName}) {
        return ${data.objectName}Mapper.updateSelective(${data.objectName});
    }

    public PageInfo<${data.entityName}> query(${data.entityName} ${data.objectName}) {
        if(${data.objectName} != null && ${data.objectName}.getPage() != null){
            PageHelper.startPage(${data.objectName}.getPage(),${data.objectName}.getLimit());
        }
        return new PageInfo<${data.entityName}>(${data.objectName}Mapper.query(${data.objectName}));
    }

    public ${data.entityName} detail(Integer id) {
        return ${data.objectName}Mapper.detail(id);
    }

    public int count(${data.entityName} ${data.objectName}) {
        return ${data.objectName}Mapper.count(${data.objectName});
    }
}

10.前端

Layui+Layuimini 单页版V2

Layuimini:基于Layui编写的一套最简洁、易用的后台框架模板(基本上与LayuiAdminPro功能上类似)

整合部分详见视频+代码

11.前后端分离项目

  • ajax(前端实现类似拦截器这样的效果比较差,改动代码太多)
  • axios(易用、简洁且高效的http库)

http://www.axios-js.com/zh-cn/docs/

Promise(不太了解的同学看一下即可)

特性

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

12.Layui集成Axios

//前后端分离的项目 数据传输的验证采用token

axios.interceptors.request.use(function(config){
    config.headers.token="zzzzzzzzzzzzzzzz";//与后端交互的时候还需要处理
    return config;
},function(error){
    return Promise.reject(error);
});


axios.interceptors.response.use(function(response){
    console.log(response.headers['content-type']);与后端交互的时候还需要处理
    if(response.status==200){
        const res = response.data;
        if(res.code==0){ //后端返回的数据为0的时候为正常数据
            return res;
        }else{
            return Promise.reject(res.msg);
        }
    }else{
        return Promise.reject(response.statusText);
    }
},function(error){
    return Promise.reject(error);
});

13.登录页面与主页

  • 前端项目的分包结构
  • 掌握调整js、css、images文件路径

14.登录功能

form.on('submit(login)', function (data) {
    data = data.field;
    console.log(data);
    axios({
        method: 'post',
        url: 'http://localhost:8888/dormitory/login',
        data: data
    }).then(function(data){
        console.log(data);
    }).catch(function(error){
        console.log(data);
    });
    return false;
});

15.跨域处理

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    //使用CorsFilter解决跨域的问题
    @Bean
    public CorsFilter corsFilter(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //允许跨域请求的域名
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedMethod("*");
        //允许任何头部
        corsConfiguration.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
        CorsFilter corsFilter = new CorsFilter(urlBasedCorsConfigurationSource);
        return corsFilter;
    }
}

16.基于Token的身份验证

​ 参考网页

​ https://www.cnblogs.com/Jason-Xiang/p/9808596.html

​ http://tool.chinaz.com/Tools/Base64.aspx

  • HTTP Basic Auth

    HTTP Basic Auth简单点说明就是每次请求API时都提供用户的username和password,简言之,Basic Auth是配合RESTful API 使用的最简单的认证方式,只需提供用户名密码即可,但由于有把用户名密码暴露给第三方客户端的风险,在生产环境下被使用的越来越少。因此,在开发对外开放的RESTful API时,尽量避免采用HTTP Basic Auth。

  • Cookie Auth

    Cookie认证机制就是为一次请求认证在服务端创建一个Session对象,同时在客户端的浏览器端创建了一个Cookie对象(jsessionId);通过客户端带上的Cookie对象来与服务器端的session对象匹配来实现状态管理的。默认的,当我们关闭浏览器的时候,cookie会被删除。但可以通过修改cookie 的expire time使cookie在一定时间内有效。

  • 基于 Token 的身份验证方法

    使用基于 Token 的身份验证方法,大概的流程是这样的:

    1. 客户端使用用户名跟密码请求登录
    2. 服务端收到请求,去验证用户名与密码
    3. 验证成功后,服务端会签发一个 Token然后保存(缓存或者数据库),再把这个 Token 发送给客户端
    4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
    5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
    6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
    Token机制相对于Cookie机制又有什么好处呢?
    • 支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.
    • 无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.
    • 更适用CDN: 可以通过内容分发网络请求你服务端的所有资料(如:javascript,HTML,图片等),而你的服务端只要提供API即可.
    • 去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可.
    • 更适用于移动应用: 当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。
    • CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。
    • 性能: 一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算 的Token验证和解析要费时得多.
    • 基于标准化:你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在多个后端库(.NET, Ruby, Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft).
    基于JWT(JSON WebToken)的Token认证机制实现

    实现Token 验证的方法挺多的,还有一些标准规范,其中JSON Web Token(JWT)是一个非常轻巧的规范 。JWT 标准的 Token 有三个部分:

    • header(头部)
    • payload(数据)
    • signature(签名)

    中间用点分隔开,并且都会使用 Base64 编码,所以真正的 Token 看起来像这样:

    eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
    

    Header

    每个 JWT token 里面都有一个 header,也就是头部数据。里面包含了使用的算法,这个 JWT 是不是带签名的或者加密的。主要就是说明一下怎么处理这个 JWT token 。

    头部里包含的东西可能会根据 JWT 的类型有所变化,比如一个加密的 JWT 里面要包含使用的加密的算法。唯一在头部里面要包含的是 alg 这个属性,如果是加密的 JWT,这个属性的值就是使用的签名或者解密用的算法。如果是未加密的 JWT,这个属性的值要设置成 none

    示例:

    {
      "alg": "HS256"
    }
    

    意思是这个 JWT 用的算法是 HS256。上面的内容得用 base64url 的形式编码一下,所以就变成这样:

    eyJhbGciOiJIUzI1NiJ9
    

    Payload

    Payload 里面是 Token 的具体内容,这些内容里面有一些是标准字段,你也可以添加其它需要的内容。下面是标准字段:

    • iss:Issuer,发行者
    • sub:Subject,主题
    • aud:Audience,观众
    • exp:Expiration time,过期时间
    • nbf:Not before
    • iat:Issued at,发行时间
    • jti:JWT ID

    比如下面这个 Payload ,用到了 iss 发行人,还有 exp 过期时间这两个标准字段。另外还有两个自定义的字段,一个是 name ,还有一个是 admin

    {
     "iss": "nihao.net",
     "exp": "1438955445",
     "name": "wanghao",
     "admin": true
    }
    

    使用 base64url 编码以后就变成了这个样子:

    eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ
    

    Signature

    JWT 的最后一部分是 Signature ,这部分内容有三个部分,先是用 Base64 编码的 header.payload ,再用加密算法加密一下,加密的时候要放进去一个 Secret ,这个相当于是一个密码,这个密码秘密地存储在服务端。

    • header
    • payload
    • secret
    const encodedString = base64UrlEncode(header) + "." + base64UrlEncode(payload); 
    HMACSHA256(encodedString, 'secret');
    

    处理完成以后看起来像这样:

    SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
    

    最后这个在服务端生成并且要发送给客户端的 Token 看起来像这样:

    eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc
    

    客户端收到这个 Token 以后把它存储下来,下回向服务端发送请求的时候就带着这个 Token 。服务端收到这个 Token ,然后进行验证,通过以后就会返回给客户端想要的资源。

    JWT的JAVA实现

    Java中对JWT的支持可以考虑使用JJWT开源库;JJWT实现了JWT, JWS, JWE 和 JWA RFC规范

    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
    </dependency>
    

    jwtutils通用类的封装

    package com.yanzhen.framework.jwt;
    
    import com.yanzhen.entity.User;
    import com.yanzhen.framework.exception.MyException;
    import io.jsonwebtoken.*;
    import org.springframework.util.StringUtils;
    
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    /**
     * jwt的工具类
     */
    public class JWTUtil {
    
        public static String token = "token";
        //秘钥
        public static String jwt_secret="yanzhen@cms@cc596183363.";
        //过期时长
        public static long jwt_expr = 3600*24*1000;
    
        //1、生成token
        public static String sign(User user){
    
            //1、指定签名的时候使用的签名算法
            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
            //2、生成签发时间
            long nowMillis = System.currentTimeMillis();
            Date date = new Date(nowMillis);
    
            //3、创建playLoad的私有声明
            Map<String,Object> claims = new HashMap<>();
            claims.put("id",user.getId());
            claims.put("userName",user.getUserName());
            //4、生成签发人
            String subject = user.getUserName();
    
            JwtBuilder builder = Jwts.builder()
                    .setClaims(claims)
                    .setId(UUID.randomUUID().toString())
                    .setIssuedAt(date)
                    .setSubject(subject)
                    .signWith(signatureAlgorithm,jwt_secret);
            //设置过期时间
            Date exprDate = new Date(nowMillis + jwt_expr);
            builder.setExpiration(exprDate);
            return builder.compact();
        }
    
        //2、验证token
        public static boolean verify(String token){
            try {
                if(StringUtils.isEmpty(token)){
                    return false;
                }
                Jwts.parser().setSigningKey(jwt_secret).parseClaimsJws(token).getBody();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        //3、获取用户信息
    
        public static User getUser(String token){
            try {
                if(StringUtils.isEmpty(token)){
                    throw new MyException("token不能为空");
                }
                if(verify(token)){
                    Claims claims = Jwts.parser().setSigningKey(jwt_secret).parseClaimsJws(token).getBody();
                    User user = new User();
                    user.setId(Integer.parseInt(claims.get("id")+""));
                    user.setUserName(claims.get("userName")+"");
                    return user;
                }else{
                    throw new MyException("超时或不合法token");
                }
            } catch (Exception e) {
                throw new MyException("超时或不合法token");
            }
        }
    
    
        public static void main(String[] args) {
            User user = new User();
            user.setId(1);
            user.setUserName("admin");
            System.out.println(sign(user));
        }
    
    }
    

17.token应用

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader(JWTUtil.token);
        //根据token获取user对象
        User user = JWTUtil.getUser(token);
        if(user == null){
            throw  new MyException("超时或不合法的token");
        }
        String newToken = JWTUtil.sign(user);
        response.setHeader(JWTUtil.token,newToken);
        //很重要
        response.setHeader("Access-Control-Expose-Headers", JWTUtil.token);
        request.setAttribute("user",user);
        return true;
    }
axios.interceptors.response.use(function(response){
    if(response.headers.token){
        store.setToken(response.headers.token);
    }
    if(response.status==200){
        const res = response.data;
        if(res.code==200){ //后端返回的数据为200的时候为正常数据
            return res;
        }else{
            return Promise.reject(res.msg);
        }
    }else{
        return Promise.reject(response.statusText);
    }
},function(error){
    return Promise.reject(error);
});

18.用户管理

19.年级管理

20.组织机构

  • ztree
  • layui集成ztree
  • 实现对ztree节点的curd
  • 数据库设计方面满足tree型结构(parentId)
  • 所有的叶子节点都是班级
layui集成ztree
layui.define(['jquery'],function(exports){
let jQuery = layui.jquery;
...


layui.link(layui.cache.base+'ztree/zTreeStyle.css')
 exports("ztree",jQuery.fn.zTree)
});


layui.config({
    base: rootPath + "lay-module/",
    version: true
}).extend({
    miniAdmin: "layuimini/miniAdmin", // layuimini后台扩展
    miniMenu: "layuimini/miniMenu", // layuimini菜单扩展
    miniPage: "layuimini/miniPage", // layuimini 单页扩展
    miniTheme: "layuimini/miniTheme", // layuimini 主题扩展
    miniTongji: "layuimini/miniTongji", // layuimini 统计扩展
    step: 'step-lay/step', // 分步表单扩展
    treetable: 'treetable-lay/treetable', //table树形扩展
    tableSelect: 'tableSelect/tableSelect', // table选择扩展
    iconPickerFa: 'iconPicker/iconPickerFa', // fa图标选择扩展
    echarts: 'echarts/echarts', // echarts图表扩展
    echartsTheme: 'echarts/echartsTheme', // echarts图表主题扩展
    wangEditor: 'wangEditor/wangEditor', // wangEditor富文本扩展
    layarea: 'layarea/layarea', //  省市县区三级联动下拉选择器
    axios: 'axios/axios', //  axios
    store: 'store/store', //  store
    ztree: 'ztree/ztree', //  axios
});
ztree操作
  • 实现树形的CURD
  • 树形采用异步还非异步

21.功能菜单权限设置

  • 管理员设置
    • 所有功能菜单、数据权限
  • 宿管员设置
    • 为每个宿管员单独设置功能菜单权限
    • 拥有自己的数据权限
      • 楼宇管理
        • 楼层
        • 宿舍
        • 学生

22.学生管理

  • 基础信息(管理员)

23.楼宇管理

24.宿舍管理

25.宿舍编号设置

26.宿舍初始化

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高校宿舍管理系统 的相关文章

  • docker-compose常见问题

    一 新版本网络桥接 问题 docker errors InvalidArgument host network mode is incompatible with port 1 24 0以前可以network mode host和ports

随机推荐

  • Python List 按照多个关键字排序

    最近刷刷题遇到的 发现还没有一模一样的答案 自己做个解答 以列表有两列为例 我们需要按照两列排序 可以利用sorted和lambda组合 l a 2 c 1 d 4 b 2 sorted l key lambda x x 1 x 0 rev
  • 小程序实现h5页面的微信支付php,微信小程序webview组件交互,内联h5页面并网页实现微信支付实现解析...

    前言 小程序支持webview以后 我们开发的好多h5页面 就可以直接在小程序里使用了 比如我们开发的微信商城 文章详情页 商品详情页 就可以开发一套 多处使用了 我们今天来讲一讲 在小程序的webview里实现微信支付功能 因为微信不允许
  • 面向对象、面向过程的思考

    把问题和答案记下来 过段时间再自己回答 几 次 2014年04月30号 师傅 思考一个问题 面向对象编程 和 面向过程编程 两类型的语言又什么区别 我 面向对象编程 最大的感觉就是分工的明确 从小的方面来说 就是把程序里面的一个个对象 类
  • 解剖上海交大女生无耻言论:只嫁外国人?

    上海交大MM的不嫁中国男人自白书原文 我是上海交大的一名女大学生 我第一次发帖子 写的不好 请大家表笑偶 每个人都有人生理想 有的人想成为英雄 有人的想成为富翁 有的人渴望成为领袖 我呢 人生最大的愿望就是嫁给一个西方男人 有人会说我很庸俗
  • 重定向与请求转发,以及它们之间的区别

    重定向 在某些情况下 针对客户端的请求 一个Servlet类可能无法完成全部工作 这时 可以使用请求重定向来完成 所谓请求重定向 是指Web服务器接收到客户端的请求后 可能由于某些条件限制 不能访问当前请求URL所指向的Web资源 而是指定
  • 高效管理之团队梯度建设

    经常听人讲 我们要建设高效的团队 如何提高团队的执行效率等等 空谈效率没有意义 这篇文章结合作者自身的经历 谈谈梯度团队是什么样子的 为什么一个有梯度的团队是高效的 以及在管理中如何建设这样的团队 梯度团队介绍 下图是我经历的一家中型互联网
  • Linux下VIM编辑器的详细使用

    1 VI编辑器的启动与退出 vi file1 新建一个文本文件为file1 q 在末行模式下退出 2 文本的操作 e file1 在当前文件下编辑新的文件 r etc passwd 实现文件的读入功能 wq 保持并退出 q 强行退出 3 光
  • Qt的容器类——QList

    定义 QList lt T gt 以数组列表形式实现 在其前后添加数组非常快 注意Qt中有很多函数返回了QList类型 要遍历这些返回的容器 必须先复制再遍历 因为Qt使用了隐式复制 所以开销并不大 当一个迭代器在操作一个容器时 不要复制这
  • 编码与解码

    什么是编码与解码 电脑是由电路板组成 电路板里面集成了无数的电阻和电容 交流电经过电容的时候 电压比较低 记为低电平 用0表示 交流电流过电阻的时候 电压比较高 记为高电平 用1来表示 所以每一个1 和0 在计算机中被称为 位 也就是bit
  • 微信开发ios上传图片到服务器,微信开发上传图片ios与安卓兼容问题

    首先检查一下引入js的版本 用最新的 直接上代码 kin img click function var ua navigator userAgent toLowerCase if ua match iphone i micromesseng
  • 使用 spring.profiles.active 及 @profile 注解 动态化配置内部及外部配置

    https blog csdn net swordsnapliu article details 78540902 引言 使用 spring profiles active 参数 搭配 Profile注解 可以实现不同环境下 开发 测试 生
  • I2C局部架构

    与子系统集成时候 APB Slave接口的master为AHB2APB Bridge I2C接口连接系统I2C总线 工作时候 先使用APB接口配置寄存器 决定I2C的工作模式 随后向指令寄存器写指令 使I2C进行数据传输操作 基本功能 可以
  • 最详细 openEuler 安装教程

    随着Centos的逐步转移 Centos8在2021年12月31号将停止维护 随而Centos7也将于2024年逐步停止维护 我们可以转向openEuler 也就是华为服务器操作系统 EulerOS 开源后命名为 openEuler 面向企
  • Android框架源码解析之(六)MultiType

    介绍 MultiType 可以简单 灵活的为RecyclerView实现多类型列表 MultiType介绍 https juejin im post 59702b606fb9a06ba14bc1b0 MultiType源码 https gi
  • Apache配置项目图片地址映射

    项目需求 将服务器物理磁盘上的某个目录 映射到apache能够访问到的url地址上 以此来达到图片和代码的分开部署 同时也方便项目后期的文件迁移 当图片资源变的越来越大 大到需要几个小时 甚至一整天的时间 来迁移图片资源时 这种分开部署的优
  • CMOS 图像传感器——Color Filter Array

    在介绍CMOS图像传感器的工作原理时候说道 像点 Sensor感光的基本单元叫做 像点 吸收入射光后会有一定概率激发出电子 这个过程叫做光电转换 光子激发出电子会被像点下方的电场捕获并存储起来备用 像点的作用可以类比成一个盛水的小桶 它可以
  • 数据库优化

    前言 毫不夸张的说咱们后端工程师 无论在哪家公司 呆在哪个团队 做哪个系统 遇到的第一个让人头疼的问题绝对是数据库性能问题 如果我们有一套成熟的方法论 能让大家快速 准确的去选择出合适的优化方案 我相信能够快速准备解决咱么日常遇到的80 甚
  • 《爬虫系列之爬取PPT》

    这次不多BB 直接上代码系列 import bs4 import requests headers user agent Mozilla 5 0 Windows NT 10 0 Win64 x64 AppleWebKit 537 36 KH
  • win10 64位 Compaq Visual Fortran(CVF)安装教程

    最近需要调试下fortran程序 它是fortran与c混编的 因此simply Fortran还不能满足需求 IVF还会涉及版本兼容与移植的问题更不想用 于是上网搜了下关于安装CVF的资料 发现似乎CVF的安装并不容易 甚至还有说不能安装
  • 高校宿舍管理系统

    高校宿舍管理系统 项目截图 1 项目概况 提到宿舍 现在无论是学校 还是工厂 都是在熟悉不过的了 学生宿舍楼 职工教员工 职工宿舍楼等等 每一栋楼房都有很多的房间 每个宿舍分配了多少个床位 住着什么人 那些床位是空的 那些房间是空的 这些都