版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
考勤管理系统之用户角色及权限的设计与实现摘要在互联网信息技术急速发展的新时代,基于微信小程序的二维码和定位等功能,我们设计了可以利用二维码和定位功能来进行签到的考勤管理系统,考勤管理员可以设置签到的地点及范围,以及系统提供导出和管理用户的考勤信息功能,请假申请功能,假期管理功能等。本文重点讲述的是该系统的用户角色及权限的设计与实现,即权限模块,对于系统权限进行设计和实现,使用redis缓存优化了系统,增强了系统的性能。关键词:考勤管理系统;用户角色及权限的设计;Redis;DesignandImplementationofUserRoleandAuthorityinTimeAttendanceManagementSystemAbstractIntheneweraofrapiddevelopmentofInternetinformationtechnology,basedontheWeChatapplet'sQRcodeandpositioningfunctions,wehavedesignedanattendancemanagementsystemthatcanusetheQRcodeandpositioningfunctionstocheckin.Andthescope,andthesystemprovidesthefunctionofexportingandmanaginguser'sattendanceinformation,leaveapplicationfunction,vacationmanagementfunction,etc.Thisarticlefocusesonthedesignandimplementationofthesystem'suserrolesandpermissions,thatis,thepermissionmodule,whichdesignsandimplementssystempermissions,optimizesthesystemusingrediscache,andenhancessystemperformance.Keywords:TimeandAttendanceManagementSystem;Designofuserrolesandpermissions;Redis;目录TOC\o"1-3"\h\u1前言 62相关技术介绍 62.1前端技术介绍 72.2Java介绍 82.3后台项目架构介绍 82.4技术架构图 103系统的介绍 103.1系统设计及功能结构 103.2系统模块介绍 123.2.1权限管理模块 123.2.2考勤统计模块 123.2.3审批模块 133.3系统用例图 144权限模块的设计与实现 144.1权限模块的设计 144.2权限模块的实现 165测试 205.1登录功能测试 205.2角色增删改查功能测试 215.3员工增删改查功能测试 225.3不同角色用户权限控制测试 236微信小程序界面 257结论 27附录1 281前言 考勤管理系统是基于微信小程序的二维码和定位等功能实现的一个给公司进行考勤管理的系统,系统支持二维码,定位,口令签到。为什么选择微信小程序呢,不仅仅是因为微信用户量大,微信小程序还有使用便捷,不需要重新下载软件,占用内存小等优点。依托微信小程序这个便捷应用环境,开发这个考勤管理系统。考勤管理系统分成小程序端,web端,小程序端用于公司员工考勤使用,web端主要支持考勤数据统计,审批流程管理,考勤规则设置,公司员工管理。考勤管理系统主要分成权限管理模块,考勤统计模块,审批模块三个模块。而本文重点研究的是考勤管理系统的权限管理模块的具体分析,对于本系统中,用户,角色,和权限的关系进行梳理,在设计过程中,与前端的实现进行交融,将页面的查看权限进行抽取,单独建立路由表,而其他权限则按页面进行划分,分别关联对应的页面。对于具体的设计与实现,将在本文后面的部分给出。2相关技术介绍2.1前端技术介绍需求来引入你需要的第三方库,Vue是MVVM模式的框架,MVVM即Model-View-ViewModel也就是数据层-dom层(用户界面层)-和中间层(处理数据和界面)。MVVM模式:提供了数据的双向绑定,分离了视图(View)和模型(Model),大大降低了代码耦合,提高了重用性。Vue.js在2.0版本就引入了虚拟DOM,使得它的初始渲染速度大幅度提升,还大大降低了内存的消耗,Vue官方甚至还与React做过实验对比,结果得出Vue的渲染优于React。近年来Vue.js也是越来越多的人使用,在国内使用Vue.js已经比使用React.js的人更多了。Vue-router是Vue.js官方的路由管理器,适用于构建SPA(单页应用程序),SPA与传统应用程序的区别就是传统应用程序切换页面会重新请求服务器获取新的完整页面,而SPA只会第一次请求加载页面,而后的每次请求,仅仅是获取必要的数据。然后,由页面中js解析获取的数据,展示在页面中,这就是SPA的核心之一:更新视图而不重新请求页面,不过这样也产生了一个缺点,如果后端不做服务器渲染,就会导致这个单页面应用是不能被爬取到数据的,这就对SEO不是很友好了。Vue-router就是SPA的路由,路由的本质就是建立起URL和页面之间的映射关系,对于Vue来说就是建立URL和组件之间的映射关系。Vue-router在实现SPA路由时,提供了两种方式:hash模式和history模式。hash模式使用URL的hash来模拟一个完整的URL,于是当URL改变时,页面不会重新加载,而history模式利用history.pushStateAPI来完成URL跳转而无须重新加载页面。Vuex是Vue.js官方的状态管理模式,为的是处理在项目庞大时,组件数量变多,遇到需要多个组件共享状态时的处理,将组件中的转态抽离,以一个全局单例模式管理,让组件树构成一个巨大的‘视图’,不管树在哪个位置,任何组件都能获取状态或者触发行为。Vuex通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,使代码变得更结构化,更易维护。这就是Vuex的基本思想,Vuex的这个思想借鉴了Flux,Redux和TheElmArchitecture。而且Vuex是专门为Vue.js设计的状态管理库,以利用Vue.js的细粒度数据响应机制来进行高效的状态更新。iView是一套基于Vue.js的开源UI组件库,主要服务于PC界面的中后台产品。Iview是时下很火的一款Vue.js的组件库,因为iView组件功能比较丰富,UI界面也很漂亮,各个组件的API也很友好,使用自由灵活。也是因为iView各个方面做得都很好,才有越来越多的人去使用它。Axios是一个基于Promise的HTTP库,Promise是ES2016的一个特性,Promise异步函数,在ES6推出后就被广泛使用,而Axios正式基于Promise来实现的一个Http库,它的底层就是XMLHttpRequests,只是用了Promise做了封装。Axios在发布后,就被众人推崇。微信小程序是不需要下载安装就可以直接使用的应用,快捷,用户量大。2.2Java介绍项目后台使用Java开发,Java是现在世界上使用人数最多的编程语言,它之所以受欢迎,是因为它是一门面向对象的语言,能够跨平台运行,不用考虑操作系统,这样子程序员可以专心考虑业务逻辑的实现,而不用担心在不同平台上运行的兼容性。它还支持泛型,Java广泛应用于企业开发和移动应用开发,虽然现在移动端的开发语言主要使用kotlin,但这门语言也是运行在java虚拟机上的。这门语言诞生在1991年,由JamesGosling等人开发,最初名称叫做Oak,但在1994年更名为Java,据说这个名字来自于Java咖啡,Java因为其自带垃圾处理机制,不用像C语言或C++那样需要程序员自身担心垃圾回收不当造成的内存泄漏,并且Java运行在Java虚拟机上,与平台无关,Java作为一门编程语言,语法严谨,有完善的异常处理机制。因此使用Java编写出来的程序安全、健壮性强,并且可移植,跨平台,Java因此成为了世界上最流行的语言。Java发展至今,使用人数众多,又有许多能人为Java编写了调用简单,但功能强大、稳定的库,许多问题也能及时在社区中容易的找到答案。Java是先将代码编译为自己的字节码程序,再由Jvm解释运行,因此只需要在各个平台上部署好Java环境后便不用担心,因此成就了Java一次编译到处运行的宣传口号。2.3后台项目架构介绍项目采用了JavaEE三层架构,分为了展示层、业务逻辑层、数据控制层。帮助开发人员更容易的关注某一层,而不必担心其它部分,对项目开发的各个环节进行了解耦。其中展示层主要用于与用户交互,接受用户数据并返回处理结果给用户,在本项目中展示层使用了Springmvc框架,框架的主要目的就是封装了许多底层操作,只对外提供了简单的接口,方便程序员进行开发,提高程序员的开发效率。SpringMVC框架是一种能够帮助我们我们实现了一种基于Java的MVC设计模式的轻量级框架,也是现在最受欢迎的web层框架,取代了以前的struts2。SpringMVC再想MVC添加了Spring的特色的IOC,也就是依赖反转功能的同时,还使应用程序高度解耦。在学习SpringMVC的过程中,我们可以知道SpringMVC是基于原生WEB开发中的DispatcherServlet来设计的,而不像是Struts2是基于filter来设计的。SpringMVC有着清晰的模块划分,每个模块有着自己独立的功能,它分为了前端控制器、请求到处理映射器、处理器适配器、验证器、表单对象、命令对象、视图解析器、处理器或页面控制器。SpringMVC还易于扩展,可以自定义组件等方式扩展自己的需求或按照自身业务自定义一部分逻辑。Dao层使用了mybatisPlus框架,该框架由中国人进行开发,基于mybatis,相当于Mybatis的增强工具,它并由修改mybatis的逻辑,没有对mybatis本身进行修改,而是在其基础之上进行了增强和拓展。帮助我们简化开发、提高开发效率。而Mybatis是个非常优秀的持久层框架,它完全避免了我们的JDBC代码后懂得设置参数和处理返回结果,帮我们自动映射结果到pojo上。框架使用了多种设计模式,在面试中也是常问点,非常值得我们学习。对于整个后台使用了SpringBoot框架进行控制反转和依赖注入,spring是现在Java开发后台中最主流的框架,有人甚至说现在学Java就是在学Spring,Spring官网提供了Java后台开发的一套框架。它是一个开源框架,于2003年兴起。由Netflix开源发布,现在Netflix也提供了微服务架构的一站式解决方案。当然本项目并没有采用微服务架构。而SpringBoot相当于对Spring的一次拓展,用过Spring的肯定都知道,在部署环境和编码的过程中需要配置大量的配置文件,再整合新的框架时又需要为新框架添加配置文件,这时非常繁琐的,而使用Springboot则简化了这些过程,对新框架的引入只需要在pom文件中添加对应的starter,也就是启动器,而做到这一点的方式也就是靠习惯大于配置原理,许多配置都默认按照习惯的方式去配置,当不满足需求时再根据需求对其进行更改,并且添加新配置也可以采用JavaConfig的方式,使用注解进行注入,这大大简化了部署和开发过程,不必像以往一样创建大量的xml文件,所有的配置文件只需一个application.yml或者perties。并且springboot嵌入了Tomcat,不必在自己下载和配置Tomcat服务器。项目使用使用了maven来进行构建,springboot本身也是依赖maven来导入依赖的。使用了SpringSecurity管理权限。在Spring搭建的环境中整合SpringSecurity非常方便,并且SpringSecutrity功能强大完善。使用NoSql非关系型数据库Redis作为缓存,用于存储权限等信息,将常用但不经常变更的信息存入缓存减少数据库查询带来的性能损耗。2.4技术架构图图2.1前端技术架构图图2.2后端技术架构图3系统的介绍3.1系统设计及功能结构考勤管理系统用于给用户进行考勤管理,并生成考勤统计信息,为管理者提供用户的考勤信息,方便公司的管理,并且可以根据管理者的想法来使用不同的考勤方式。为方便用户的使用还提供了微信小程序端来进行考勤。本考勤管理系统的功能菜单分为以下:首页:根据不同角色的进入显示,用于给普通用户签到及查看一些数据的,用于后台管理权限的用户查看系统的使用情况及当天的考勤情况及签到等角色管理:用于超级管理员编辑系统角色的权限或者增删角色。公司管理-部门管理:用于公司管理员管理公司的部门。公司管理-员工管理:管理系统的用户,拥有权限的用户可以新增用户,删除角色或者编辑用户的部门及角色。考勤管理-考勤方式设置:拥有权限的用户可以在本业面设置公司考勤的方式,以及设置修改不同方式的一些具体的参数,重要的是,本页面是显示考勤二维码的地方。考勤管理-假期设置:拥有权限的用户可以在本页面为公司调整假期的设置。我的审核:在申请流程进行中,若有需要你审核的事件就会在这里显示,本页面还可以查看审核记录或者某些抄送审核。我的申请-请假申请:当你需要请假时,则需在此页面填写信息进行申请。我的申请-补卡申请:当你忘记打卡或者某些情况下需要补卡的时候,需要在本页面填写信息进行申请。考勤记录-考勤记录:拥有权限的用户可以在本页面查看系统用户的考勤记录,还提供了数据的分析,数据的导出等功能。考勤记录-我的考勤记录:显示了用户的考勤记录。考勤记录-考勤统计:用图表显示了考勤的统计信息。个人中心-修改密码:用户修改密码的页面。图3.1系统功能结构图3.2系统模块介绍3.2.1权限管理模块权限管理模块,什么是权限管理呢,就是对于用户的显示页面和操作的限制,管理用户所能看到的菜单,以及进入不同菜单页所能看到的数据,进行的操作等的控制和管理,简单来说就是对于登录用户,我们要根据用户的信息来显示他具备权限的菜单,在进入页面后,又根据用户的信息来显示他具备权限的信息,并根据用户的信息在页面显示他具备权限的操作按钮。在调用后台接口是,服务器也得先根据用户的信息来判断他是否用对应的权限。用一句话概括来说就是,用户可以访问而且只能访问自己被授权的资源,不能多也不能少。权限管理的应用十分的广泛,对于权限管理模块,他需要具备以下功能。①路由菜单管理:对登录后用户的菜单进行控制,不同用户登录应只能看到自己被授权的菜单;②页面显示管理:对登录后用户的菜单进行控制,不同用户登录应只能看到自己被授权的信息;③操作按钮管理:对登录后用户的菜单进行控制,不同用户登录应只能操作自己被授权的操作按钮;④角色权限管理:管理角色及编辑角色的权限;⑤用户角色管理:编辑用户的角色;3.2.2考勤统计模块对考勤管理系统中的考勤统计模块,出于便利性和安全性考虑,前端选择好相应过滤条件和显示方式,将条件交给后端,后端将考勤数据从服务器上的MySql数据库中取出后,在后端进行分析封装,加密后再返回给前端浏览器显示,前端根据数据动态显示表格或者更加直观清晰明了的图表。本考勤管理系统中的考勤数据统计模块具体应该实现如下功能:①用户验证功能:只有登录用户具有相应的权限,才能展示考勤数据给用户观看及分析;②网络交互功能:浏览器通过服务后台暴露的接口,使用http协议向服务端发送请求,实现浏览器和服务器之间的交互和数据传输;③考勤数据查询功能:前端提供过滤条件和排序条件,后台根据用户指定条件,查询相应数据,封装加密后返回给前端,前端能够根据用户需要的方式展示数据,使用表格显示、生成直观的图表或者导出数据,不仅可以查询某个员工的详细数据,还能够查询某一批员工的数据;④统计功能:根据用户需求,统计一段时间或是某个部门等条件需求按照一定的条件或方式统计数据,返回给前端统计后的结果,根据用户的需求展示数据或者导出数据为excel文件,并且要保证统计数据的准确性;⑤分析功能:根据用户需要的条件对数据按照一定的算法进行分析,比如展示用户迟到次数随日期变化的趋势,如果用户有相应需求则可以尽量实现相应的数据分析功能;3.2.3审批模块审批模块是考勤管理系统中的较为重要的一个模块,审批模块提供了多个申请功能流程,以及审批功能。审批模块主要由请假申请,补卡申请,以及审核功能组成。①请假申请功能:当你因故需要请假时需要进行请假申请,不同的请假类型有不同的限制,请假类型包括但不限于年假,事假,病假,调休,产假等,通过审批后方为成功请假;②补卡申请功能:当你忘记上下班时间打卡时,在每月的限额中,你可以进行补卡申请,通过审核后方补卡成功;③审核功能:在上面介绍的功能中,会有部分流程需要特定的用户来进行审批,每个用户都可能是审批人,审核功能有通过或者不通过,当流程走到对应用户时,可对申请进行操作;3.3系统用例图图3.2系统用例图4权限模块的设计与实现4.1权限模块的设计对于考勤管理系统的用户角色及权限的设计,事实上就是用户和权限关系的分离解耦,一个用户对应的权限就有十几个,你如果每个新的用户都需要给他一个一个权限去设置的话,重复性和表的设计都不好处理。于是就在中间加入了一个角色表。角色表的设计,让我们能更加灵活的处理权限和用户之间的关系。角色,可以按照公司对不同岗位需求划分出不同的权限集合,这样对于不同的用户我们就可以直接对他们对角色做关联,大大的降低了耦合。而当公司新增工作岗位时,这个新增的岗位需要的一些权限还与现有的角色不同,那么我们可以为他新增一个角色,关联上他需要的特定的权限。而在本系统的用户角色及权限的设计时,考虑到使用的技术,又对权限做了新的设计,将权限对页面做划分,将页面的菜单提取出来,形成菜单表,并根据Vue-router的路由参数做详细的设计,具体的详细设计在下面在给出。而页面的一些具体权限,则形成权限表,并对菜单表做外键关联。在确定了用户表,角色表,菜单表,权限表后,就该考虑他们的关系了,显然,用户和角色是多对多的关系,角色和菜单也是多对多的关系,角色和权限也是多对多的关系。确定了关系,就能中间表的的设计,结合关系我们现在能确定的表有,sys_user(用户表),sys_role(角色表),sys_menu(菜单表),sys_permission(权限表),sys_user_role(用户角色表),sys_role_menu(角色菜单表),sys_role_permission(角色权限表)。 用户角色表将用户和角色的关系进行转换,用户角色表对用户表和角色表都成了一对多的关系,同理角色菜单表,角色权限表都是一样的,都是为了转换多对多的关系而建的表。实体类的E-R图如下:图4.1E-R图对于sys_menu(菜单表)的设计,我们结合了前端技术vue-router的路由库来对前端的路由进行控制,sys_menu(菜单表)的字段有id,name、redirect、title、hide_in_menu、component、parent_id、children_id、sort、icon。菜单表主要是为了对前端的菜单也就是路由进行控制,其中name是作为路由的路由名称,以及生成链接路径来设计的,redirect是用作路由的重定向,title就是对应页面的标题,hide_in_menu是为了设置对应的菜单要不要在主页面的左侧菜单栏显示,component是用来存放对应页面在前端文件的位置(url),parent_id以及children_id则是为了辨明对应父级菜单以及子菜单,sort是用来做菜单排序用的,icon则是用来存放对应菜单的图标的,其余的表在这就不做详细说明了。在用户登录前在前端只注册登录,404等页面,并做路由拦截,对于未登录的访问做默认跳转登录页,在用户登录后则动态注册路由,对于没有权限的页面依旧没法跳转,这样的话,就能很好的对用户的权限做管理了,也能避免用户直接对路由做操作。来跳转他没有权限的页面。4.2权限模块的实现对于权限模块来说,最重要的一个就是不能让用户出现“越权”访问的情况,什么是越权访问的情况呢,就是访问了某些他并没有权限的资源,例如:在用户a的权限中他并没有b页面的权限,但他却通过某种情况成功的访问了b页面,这就是“越权”访问。而对于这种管理,在我们这种系统中是利用Vue-router动态路由注册来实现的页面管理,在设计方面已经详细的讲了表的设计,这里就详细讲具体的实现吧,首先我们在用户未登录情况下只注册登录页,404页面并且用Vue-router的全局守卫做路由拦截,if(!token&&!==LOGIN_PAGE_NAME){next({name:LOGIN_PAGE_NAME});}elseif(!token&&===LOGIN_PAGE_NAME){next();}elseif(token&&===LOGIN_PAGE_NAME){next({name:config.homeName})}else{if(store.state.user.hasGetInfo){initRouters(store);next();}else{store.dispatch('getUserInfo').then(()=>{initRouters(store);next();}).catch(()=>{setToken('');next({name:LOGIN_PAGE_NAME})})}}上面就是Vue-router登录拦截的实现,其中token是用的cookies保存的,给我们用来判断用户是否登录,以及用来給后端做身份验证的。对于全局守卫中的拦截,我们做了多次的判断,对未登录且要跳转的页面不是登录页进行拦截给他跳转到登录页,对未登陆且要跳转的页面是登录页放行,对已登录且要跳转的页面是登录页进行拦截跳转到后台主页,然后就是对用户是否获取信息做判断了,store是我们使用的Vuex全局状态管理器,判断有没有加载用户信息,若是加载了,则直接进行初始化路由,若是没有加载用户信息,则先加载用户信息在初始化路由,为了防止用户信息加载失败的出现问题,在出现异常时清空token并且给用户跳转到登录页。这就是Vue-router全局守卫的大概实现。List<Menu>menusFromRoles=roleService.getMenusFromRoles(roleSet);HashMap<Integer,JSONArray>menuMap=newHashMap<>();while(true){HashSet<Integer>parentIds=newHashSet<>(menusFromRoles.size());for(MenumenusFromRole:menusFromRoles){IntegerparentId=menusFromRole.getParentId();parentIds.add(parentId);Stringname=menusFromRole.getName();inti=name.indexOf("_");if(i==0)menusFromRole.setPath("/");elsemenusFromRole.setPath("/"+name);Strings=JSONObject.toJSONString(menusFromRole);JSONObjectjsonObject=JSONObject.parseObject(s);jsonObject.remove("childrenId");jsonObject.remove("parentId");JSONObjectmetaObject=newJSONObject();metaObject.put("title",jsonObject.remove("title"));metaObject.put("hideInMenu",jsonObject.remove("hideInMenu"));metaObject.put("icon",jsonObject.remove("icon"));jsonObject.put("meta",metaObject);JSONArrayjsonArray=menuMap.get(parentId);if(jsonArray==null){jsonArray=newJSONArray();menuMap.put(parentId,jsonArray);}jsonArray.add(jsonObject);}if(parentIds.size()==1&&parentIds.contains(0))break;QueryWrapper<Menu>queryWrapper=newQueryWrapper<>();queryWrapper.in("id",parentIds);menusFromRoles=menuService.list(queryWrapper);}JSONArrayjsonArray=menuMap.remove(0);if(jsonArray==null)returnResultVO.success();LinkedList<JSONObject>list=newLinkedList<>();for(Objecto:jsonArray){JSONObjectjsonObject=(JSONObject)o;list.add(jsonObject);}while(list.size()!=0){JSONObjectjsonObject=list.poll();JSONArrayarray=menuMap.remove(jsonObject.getIntValue("id"));if(array!=null)for(Objecto:array){JSONObjectjsonObject1=(JSONObject)o;list.add(jsonObject1);}jsonObject.put("children",array);jsonObject.remove("id");}returnResultVO.success(jsonArray.toJSONString());上方的代码是处理菜单表,根据用户角色返回他可以访问的路由表,首先用拿到的用户角色去查找对应的路由表获取到最下层的路由信息,在对获取到的路由信息进行处理,首先我们循环下层的路由信息进行处理,并将处理好的数据信息根据他们的parentId的信息,存在hashMap同一个键对应的值的Array信息里,然后又根据parentId拿到对应的路由信息,循环处理,在prentId长度为一且包含0时退出循环。在获取出路由信息后先判断拿到的数据长度,如果一级菜单长度为0则不需要在继续处理了,直接返回结果,若不为0则还需要继续处理,继续将子菜单放到对应的位置上。处理完成后的数据大概格式就是下面这样的:{path:"/",name:"_home",redirect:'/home',meta:{title:'首页',hideInMenu:false,icon:'md-home'},component:"views/home/index.vue",children:[{path:'/home',name:'home',meta:{title:'首页',hideInMenu:false,icon:'md-home'},component:"views/test/index.vue"}]},前端对于拿到的数据还需要再次进行处理,因为前端路由的数据结构还是跟后端传过来的数据有一点点区别的,主要的区别还是在component这里不一样,对此我封装了工具函数进行处理。constbackendMenusToRouters=(menus)=>{letrouters=[]forEach(menus,(menu)=>{letroute=backendMenuToRoute(menu)if(menu.children&&menu.children.length!==0){route.children=backendMenusToRouters(menu.children)}routers.push(route)})returnrouters}constbackendMenuToRoute=(menu)=>{letroute=Object.assign({},menu)ponent=(resolve)=>require([`@/${ponent}`],resolve)returnroute}这就成功的处理了路由树,将处理路由的方法放在Vuex中进行管理,然后在Vue-router全局守卫的initRouters()函数中判断他是否已经注册了路由,注册了就直接跳转,没有注册则进行路由注册,这样就成功的管理了用户的权限,防止了用户出现“越权”访问的情况。但是这样处理每次页面都需要重新访问数据库,就会频繁的访问数据库,很是影响系统的性能,对于这种情况,我们就引入了Redis来对用户的数据进行缓存,在用户第一次访问系统并登录后,调用了获取路由信息的接口时,在获取到用户路由信息后,用Redis对用户的路由信息进行存储,这样一来,用户还需要路由信息时就不在需要重新查询数据了,可以直接在Redis中取出路由信息就可以了,这样就大大提升了系统的性能。对于页面的一些具体的权限,我们也在Vue-router全局守卫中拿到了,再页面渲染时进行处理判断,比对权限内容,对于用户没有的操作权限,直接不渲染出来,这样用户就不可能操作到他并没有的权限的内容。在用户登录后进行的页面跳转会首先进入Vue-router全局守卫,在进行判断后请求接口,获取用户信息以及路由信息表,处理获取来的路由信息后进行注册路由信息表,然后在通过通过守卫,成功进入页面,在页面渲染时判断对应的用户是否拥有权限,再进行渲染,没有权限的就不渲染对应的节点,这样就实现了权限管理,也不会出现“越权”访问的情况了。5测试5.1登录功能测试测试考勤管理系统的用户登录是否正常,在用户输入时是否会进行验证,用户密码或用户名输入错误时是否会提示,用户名密码与数据库验证一致时是否能成功登录系统。表5.1登录功能测试用例用例描述用来测试考勤管理系统的登录功能是否正常前置条件存在正确的用户名和密码;登录页面正常加载操作步骤输入数据预期结果实际结果输入正确的用户名和密码用户名:test密码:123456登录成功,跳转首页登录成功,跳转首页输入错误的用户名和正确的密码用户名:head密码:123456登录失败,弹出弹窗用户名或密码错误登录失败,弹出弹窗用户名或密码错误输入正确的用户名和错误的密码用户名:test密码:12345678登录失败,弹出弹窗用户名或密码错误登录失败,弹出弹窗用户名或密码错误图5.1测试登录功能5.2角色增删改查功能测试测试考勤管理系统中的角色的新增,删除,修改,查询。表5.2角色的增删改查功能测试用例用例描述用来测试考勤管理系统的角色增删改查功能是否正常前置条件存在正确的角色和权限;后台主页正常加载;角色管理页面正常加载操作步骤输入数据预期结果实际结果点击角色管理菜单按钮无角色管理页面正常加载,出现默认分页查询结果角色管理页面正常加载,出现默认分页查询结果输入角色名,点击查询按钮角色名:test返回角色名中带有test的数据返回角色名中带有test的数据点击新增按钮,在弹窗中输入角色名和描述,点击新增按钮角色名:test2描述:这是用来测试的数据弹出弹窗提示新增角色成功,并关闭弹窗弹出弹窗提示新增角色成功,并关闭弹窗鼠标移动到需要删除的角色上面,点击显示出来的确认无弹出弹窗提示删除成功,并刷新当前的分页查询弹出弹窗提示删除成功,并刷新当前的分页查询鼠标移动到需要删除的当前页的最后一条角色上面,点击显示出来的确认无弹出弹窗提示删除成功,并自动跳转到前一页的分页查询弹出弹窗提示删除成功,并自动跳转到前一页的分页查询点击修改权限,在弹窗中修改当前角色的权限,修改后点击保存按钮无弹出弹窗提示修改成功弹出弹窗提示修改成功图5.2测试角色增删改查功能5.3员工增删改查功能测试测试考勤管理系统的员工的新增,修改,查询,删除功能。表5.3员工的增删改查功能测试用例用例描述用来测试考勤管理系统的员工增删改查功能是否正常前置条件存在正确的角色和权限;后台主页正常加载;员工管理页面正常加载操作步骤输入数据预期结果实际结果点击员工管理菜单按钮无员工管理页面正常加载,出现默认分页查询结果员工管理页面正常加载,出现默认分页查询结果点击分页中的按钮2无页面重新查询,页面加载出查询结果的第二页页面重新查询,页面加载出查询结果的第二页输入用户名,点击查询按钮用户名:test返回用户名中带有test的数据返回用户名中带有test的数据输入姓名,点击查询按钮姓名:test返回姓名中带有test的数据返回姓名中带有test的数据输入手机号,点击查询按钮手机号:132返回手机号中带有132的数据返回手机号中带有132的数据下拉选择部门test,点击查询无返回部门为test的数据返回部门为test的数据点击新增按钮,在弹窗中输入新增员工的信息,点击新增姓名:test3,用户名:test3,工号:test003,手机号:132322343334,部门选择test,角色选择ROLE_1弹出弹窗提示新增成功,并刷新当前查询结果弹出弹窗提示新增成功,并刷新当前查询结果点击修改按钮,修改用户test3的信息,点击保存手机号部门选择test1,角色选择ROLE_2弹出弹窗提示保存成功,并刷新当前查询结果弹出弹窗提示保存成功,并刷新当前查询结果鼠标移动到需要删除的用户上面,点击显示出来的确认无弹出弹窗提示删除成功,并刷新当前的分页查询弹出弹窗提示删除成功,并刷新当前的分页查询鼠标移动到需要删除的当前页的最后一个用户上面,点击显示出来的确认无弹出弹窗提示删除成功,并自动跳转到前一页的分页查询弹出弹窗提示删除成功,并自动跳转到前一页的分页查询图5.3测试员工增删改查功能5.3不同角色用户权限控制测试 测试考勤管理系统拥有不同角色的用户登录后的菜单权限的管理及是否能越权访问。表5.4不同用户权限控制测试用例用例描述用来测试考勤管理系统的拥有不同角色的后台菜单权限及操作权限是否受控前置条件存在正确的角色和权限;后台主页正常加载;拥有多个分别拥有不同角色的用户账号(test账号拥有所有页面权限,test2拥有部分页面权限但拥有用户管理页面的编辑权限,test3拥有用户管理页面权限但没有编辑权限)操作步骤输入数据预期结果实际结果输入test用户账号密码,点击不同的页面查看是否正常用户名:test密码:123456后台所有页面正常显示,菜单栏正常显示员工管理页面正常加载,出现默认分页查询结果输入test2用户账号密码,查看页面是否正常显示,并尝试越权访问角色管理页面用户名:test2密码:passwd地址栏输入:/role后台所有页面正常,菜单栏正常,越权访问角色管理页面出现404页面后台所有页面正常,菜单栏正常,越权访问角色管理页面出现404页面。输入test3用户账号密码,查看页面员工管理页面是否可编辑用户名:test3密码:123456后台页面正常,菜单栏正常,员工管理页面没有新增,修改,删除等按钮后台页面正常,菜单栏正常,员工管理页面没有新增,修改,删除等按钮图5.4test用户登录后的员工管理页面图5.5test2用户登录后的员工管理页面图5.6test3用户登录后的员工管理页面测试通过率:100%6微信小程序界面微信小程序端是员工用来进行签到的手机端小程序,便捷;图6.1微信小程序员工登录页面图6.2微信小程序员工主页图6.3微信小程序位置签到图6.4微信小程序口令签到7结论对于考勤管理系统权限管理模块,已经给出了具体的设计和实现方案,并进行测试,对于考勤管理系统的权限管理,结合使用的技术做具体的实现,在确定实现权限管理这个模块的时候,需要确定对应使用的技术,在来考虑对应的设计和实现。充分的结合你所使用的技术,来设计数据库,实体类。这样才能更好的去实现前端的展示,以及对用户权限做控制。同时在实现时,也考虑到对服务器的优化,用Redis做优化,解决频繁请求对服务器和数据库造成太大压力的问题。考勤管理系统主要是用于公司考勤来使用的。使用微信小程序来签到使用户使用更为便捷。参考文献[1]林磊,骆建彬,邓宪,等.管理信息系统中基于角色的权限控制[J].计算机应用研究,2002(6):82-84.谢辞大学四年已经悄悄过去,这份毕业设计是给我们大学生活的一份结束笔记,也让我们对大学生活有一份记忆。这份毕设的完成,对我们大学生活画上了一个完美的句号,在大学四年里,遇到了许许多多的老师,他们给了我很大的帮助,也遇到了许多同学,收获了很多朋友。在完成毕设的时间,因为疫情的原因,无法正常归校。希望疫情早日结束,大家回归正常的生活。在完成这份毕设的时候,很感谢毕业设计导师何亮对我的帮助。也非常感谢大学四年,各个老师和同学对我的帮助!附录附录1程序源代码/***系统菜单服务实现类*/@ServicepublicclassMenuServiceImplextendsServiceImpl<MenuMapper,Menu>implementsMenuService{@AutowiredprivateRoleServiceroleService;@AutowiredprivateMenuServicemenuService;@OverridepublicResultVO<String>getMenuFromRole(){HashSet<GrantedAuthority>authorities=(HashSet<GrantedAuthority>)SecurityAuthUtil.getCurrentUser().getAuthorities();Set<String>roleSet=newHashSet<>();for(GrantedAuthorityauthority:authorities){roleSet.add(authority.getAuthority());}List<Menu>menusFromRoles=roleService.listMenusFromRoles(roleSet);HashMap<Integer,JSONArray>menuMap=newHashMap<>();while(true){HashSet<Integer>parentIds=newHashSet<>(menusFromRoles.size());for(MenumenusFromRole:menusFromRoles){IntegerparentId=menusFromRole.getParentId();parentIds.add(parentId);Stringname=menusFromRole.getName();inti=name.indexOf("_");if(i==0)menusFromRole.setPath("/");elsemenusFromRole.setPath("/"+name);Strings=JSONObject.toJSONString(menusFromRole);JSONObjectjsonObject=JSONObject.parseObject(s);jsonObject.remove("childrenId");jsonObject.remove("parentId");JSONObjectmetaObject=newJSONObject();metaObject.put("title",jsonObject.remove("title"));metaObject.put("hideInMenu",jsonObject.remove("hideInMenu"));metaObject.put("icon",jsonObject.remove("icon"));jsonObject.put("meta",metaObject);JSONArrayjsonArray=menuMap.get(parentId);if(jsonArray==null){jsonArray=newJSONArray();menuMap.put(parentId,jsonArray);}jsonArray.add(jsonObject);}if(parentIds.size()==1&&parentIds.contains(0))break;QueryWrapper<Menu>queryWrapper=newQueryWrapper<>();queryWrapper.in("id",parentIds);menusFromRoles=menuService.list(queryWrapper);}JSONArrayjsonArray=menuMap.remove(0);if(jsonArray==null)returnResultVO.success();LinkedList<JSONObject>list=newLinkedList<>();for(Objecto:jsonArray){JSONObjectjsonObject=(JSONObject)o;list.add(jsonObject);}while(list.size()!=0){JSONObjectjsonObject=list.poll();JSONArrayarray=menuMap.remove(jsonObject.getIntValue("id"));if(array!=null)for(Objecto:array){JSONObjectjsonObject1=(JSONObject)o;list.add(jsonObject1);}jsonObject.put("children",array);jsonObject.remove("id");}returnResultVO.success(jsonArray.toJSONString());}}/***vue-router****/importVuefrom"vue";importVueRouterfrom"vue-router";importstorefrom'@/store'importViewfrom'view-design';importroutesfrom"./routers";import{getToken,setToken}from'@/libs/util';importconfigfrom'@/config';Vue.use(VueRouter);constrouter=newVueRouter({routes,mode:'history'})constLOGIN_PAGE_NAME='login';//初始化路由constinitRouters=(store,to,next)=>{//这个人登录了已经if(store.state.user.hasGetInfo){//路由加载过了if(store.state.app.hasGetRouter&&store.state.app.routers&&store.state.app.routers.length>0){}else{//加载路由store.dispatch('getRouters').then(routes=>{//路由重置一下把404放最后router.addRoutes(routes)router.addRoutes([{path:"*",redirect:"/page404"}])}).catch(()=>{}).finally(()=>{})}}}router.beforeEach((to,from,next)=>{View.LoadingBar.start();consttoken=getToken();if(!token&&!==LOGIN_PAGE_NAME){//未登录且要跳转的页面不是登录页next({name:LOGIN_PAGE_NAME//跳转到登录页});}elseif(!token&&===LOGIN_PAGE_NAME){//未登陆且要跳转的页面是登录页next();//跳转}elseif(token&&===LOGIN_PAGE_NAME){//已登录且要跳转的页面是登录页next({name:config.homeName//跳转到homeName页})}else{if(store.state.user.hasGetInfo){initRouters(store);next();}else{store.dispatch('getUserInfo').then(()=>{initRouters(store,to,next);next();}).catch(()=>{setToken('');next({name:LOGIN_PAGE_NAME})})}}})router.afterEach((to)=>{View.LoadingBar.finish();window.scrollTo(0,0);})
HYPERLINK电脑文件整理懒招从来都是不会经常整理文件的,不过时间一长,众多的文档分布在硬盘的各个角落,用目录进行整理保存,工作量大、查看起来也不方便且还会浪费不少的磁盘空闻;用压缩工具打包,尽管可以节约空间但是却无法直接编辑修改或查看压缩包中的文件。这些招,懒人怎么会用,他们自有妙招!再多再乱的文件也能整理得井井有条,关键是不费力哦!
懒招1,自动提取乱中取胜
小张起初将照片、Office文档、电影、音乐等文件一股脑地存放在某一个磁盘分区,刚开始文件少使用起来倒也方便,但随着时间的推移,文件数量剧增,每次找所需的文件都要瞪大眼睛,不过有了MY文档管理器(下载地址:)就不用担心了。
第一步,下载MY文档管理器,解压到任意目录,直接双击其中的可执行性文件即可使用。依次单击“节点操作→添加节点”,分别添加多个节点,如“办公文档”、“电影”等分类,这样做的目的是方便归类。
第二步,在小张的F盘中的TEST目录下有众多的RM、MP3、JPG、DOC、TXT格式的文件,现在他要把JPG格式的文件提取到“照片”类别中。依次单击“系统配置→文件过滤”选项,打开Dialog对话框,输入“*.doc”,单击“添加”按钮,意思是过滤掉所有类型为“.DOC”的文件。然后按照同样的方法,将“*.txt”、“*.rm”、“*.MP3”一一添加进来。
第三步,双击左侧窗格中的“照片”节点,然后依次单击“记录操作→导入记录树”命令,在打开的对话框中单击浏览按钮,打开“F:\test”目录,单击“确定”按钮之后就可以将格式为JPG的文件提取出来并添加到“照片”节点中了。
懒招2,不同的电脑统一的管理
小张是电爱的Fans,工作之余常常为杂志写稿,他写完的和正在处理的稿件一般都存在一个稿件文件夹里。不过时间一长,家里的电脑(PC1)和单位的电脑(PC2)上都有这个文件夹。时常需要通过移动硬盘(U盘)在两台电脑之间传递,使用和管理都很不方便。不过他现在用优盘就可以统一管理了。
第一步,将上文提到的那个MY文档管理器解压后直接拷贝到优盘上。把优盘插到PC1上,并运行软件,依次单击“记录操作→导入记录树”命令,在随后弹出的对话框中设置好“稿件”文件夹的根目录,将“导入深度”设置为“5”,单击“确定”后,稍等片刻,软件就把PC1上的“稿件”导入到MY文档管理器中。
小提示:通过这种方式导入到程序中的仅仅是文件的路径、文件名等属性信息,并不是文件本身。
第二步,把优盘插到PC2上,按照同样的方法导入PC2上的“稿件”文件。以后要编辑“稿件”里的文件,你自己根本不用记住哪台电脑的哪个路径,只要把优盘插入到电脑,运行MY文档管理器,就可以直接编辑了。
第三步,为方便在异地使用,小张决定为当前正在处理的稿件增加一个副本。在需要异地处理的稿件上右键单击,选择“复制文件到(自动添加副本)”命令,在弹出的对话框中将保存目录设置为优盘上的某个目录即可。这样,就可以在优盘上编辑PC1或PC2的稿件了。
小提示:对于PC1、PC2上的同名文件,MY文档管理器以不同的磁盘号+文件路径来标识文件记录,因此,对于不同电脑上的同名文件,甚至是路径和文件名完全相同的文件,程序也可以准确识别哪个是哪个。
懒招3多种文件批量移动
要将文件管理得井然有序,就免不了要进行复制、删除、移动等等操作,如果一个个进行操作,工作量是非常巨大的。这时我们就需要借助于BelvedereAutomated(下载地址:.com/assets/resources/2008/03/Belvedere%200.3.exe)进行批量操作了。例如我们想把“F:\test”目录中的所有照片移动到F盘中的“北京游照片”目录中,可以按以下方法进行。
第一步,建立“F:\test”目录后在“rule”一栏中,单击“+”按钮,建立一个规则。在“Descriptior”文本框中为当前规则起一个名字如“批量整理移动”。单击第一个下拉列表,在这里可以选择Name(文件名)、Extension(扩展名)、Size(大小)等进行操作,这里选择扩展名“Extension”。单击第二个下拉列表,在这里设置的是操作条件,有is(是)、isnot(不是)、contains(包含)等操作可供选择,这里选择的是“is”。接下来,在最后的文本框中输入图片文件的扩展名,示例中是“JPG”。定义的规则合起来的意思就是“扩展名是JPG”。
第二步,在“Dothefollowing”区域设置操作动作,单击第一个下拉列表进行操作动作的选择,有“Movefile(移动)、Renamefile(重命名)、Deletefile(删除)”等动作可供选择,我们要批量移动,那就选择重命名“Movefile(移动文件)”。接下来,单击后面的按钮选择“F:\北京游照片”目录。
第三步,规则设置完毕,单击“Test”按钮应用规则,程序即可一次性地将所有扩展名为“JPG”的图片文件移动到“F:\北京游照片”目录中了。
懒招4提纲挈领一点即得
在前面几大懒招的帮助下,你电脑里的文件应该已经有点类别了吧。如果从此想告别懒人的生活,那就要养成管理文件的好习惯了。
第一步,在你保存资料的电脑分区中,要接类别建立多个文件夹,可以按用途分为:学习、娱乐、暂存、工作、下载,在娱乐下又可以建立二级目录:电影、歌曲、动画等。也可以按照常见的文件性质进行分类,例如分为:图片、电影、电子书、安装文件等,当然也可以按照你的需要再建立二级目录,以后每有文件需要保存就按这个类别保存到相应的目录。
第二步,虽然现在已经把文件分门别类存放了,但时间长了,目录太深,一层一层查找也很麻烦的,在EXCEL里建一个目录就可以统一管理了。运行EXCEL后,新建一个表格,然后按照我们的分类方式隔行输入:图片、电影、电子书,在图片分类下再建立二级目录名,例如明星、汽车、壁纸等。
第三步,右键单击“图片文字”,选择“超链接”,在弹出的对话框中选择电脑里图片目录文件夹,单击“确定”后EXCEL里的“图片”文字就变成彩色。用同样的方法为一级目录的“电影、电子书”和二级目录的“明星、汽车、壁纸”等添加超链接。然后将这个EXCEL文件命名为文件目录,保存到桌面上,以后打开这个文档,直接单击相应的文字,比如单击“壁纸”,就可以切换到壁纸文件夹了。
小提示:如果要更改某个超链接,直接右键单击该文字,选择“编辑超链接”就可以了。本人的电脑分类原则简述如下。
硬盘的第一层(请在自己的件夹中右键“按组排列”查看)
第一位字母表示A生活娱乐B教学C工作D安装程序
第二位字母表示只是流水号
AA影视
AB音乐
AC阅读
AD图片
AE相册
生活娱乐
BA计算机
BB英语
BC运动
BD游戏攻略
BE衣食住行
BF文艺
教学
CA管理制度
CB流程图
CC程序文件
工作
DA娱乐
DB其它
安装程序
硬盘的第二层(进入“AA影视”的文件夹举例)
第一位字母表示只是流水号
第二位字母表示只是流水号
AA电影
BA电视剧
CAMTV
硬盘的第三级(进入“AA电影”的文件夹举例)
第一位字母表示A动作片B剧情片C动画片
第二位字母表示A未看过B已看过
AA导火线
AB尖峰时刻
动作片
BA独自等待
剧情片
CB机器猫
CB狮子王
动画片
利用“字母排序”和“按组排列查看”可以使文件查看和存放简洁明了,结合自己资料的特点和实际需求,给自己定一个分类原则并严格执行。个人电脑资料的资源会得到高效而充分的利用。电脑文件管理八条小技巧
在电脑的内部,在电脑的桌面上,在“资源管理器”中,充斥着无序与混乱,这种虚拟的混乱极大地影响了电脑的性能和
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 深度解析(2026)《GBT 33358-2016政府热线服务规范》(2026年)深度解析
- 卵圆孔未闭规范化诊疗中国专家共识2026解读
- 医疗数据安全标准:区块链技术的行业应用前景
- 医疗数据安全成熟度评估:区块链驱动的安全审计创新
- 医疗数据安全意识培养:区块链实践
- 医疗数据安全区块链技术的生态合作与价值共创
- 医疗数据安全分级与区块链法规适配性研究
- 医疗数据安全共享技术体系
- 2026届上海市实验学校高二生物第一学期期末监测试题含解析
- 北京市丰台区2026届高二上数学期末考试试题含解析
- 2025年榆林市住房公积金管理中心招聘(19人)备考笔试试题及答案解析
- 安徽省A10联盟2025-2026学年高三上学期12月学情检测化学试题(含答案)
- 2025年金属非金属矿山(地下矿山)安全管理人员证考试题库含答案
- 万科物业安全管理方案
- 2025秋苏教版(新教材)小学科学三年级上册知识点及期末测试卷及答案
- 2025年及未来5年中国非晶合金变压器市场深度分析及投资战略咨询报告
- 中文核心期刊论文模板(含基本格式和内容要求)
- 钢结构工程质量检测报告
- 2024-2025学年云南省普通高中高二下学期期末学业水平合格性考试数学试卷
- GB/T 18213-2025低频电缆和电线无镀层和有镀层铜导体直流电阻计算导则
- 泰康人寿会计笔试题及答案
评论
0/150
提交评论