rbac权限和多级请假设计的流程演示和前端页面实现

本文主要是介绍rbac权限和多级请假设计的流程演示和前端页面实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

登录账号:t6普通用户 t7部门经理 m8总经理 密码都为:test
多级请假:7级及以下申请请假需要部门经理审核,若是请假时长超过72小时,则需要总经理审核,7级申请请将需要总经理审核,总经理请假自动审核通过。申请和审核流程都需要生产消息通知。
(前后端不分离)
业务流程测试:王美美[高级研发工程师](7级以下用户)登录并申请请假(超过了72小时需要部门经理和总经理申请)
在这里插入图片描述
王美美请假(查过72小时),需要部门经理和总经理审核
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
部门经理(7级)登录消息通知审核消息并处理审核
在这里插入图片描述
在这里插入图片描述
部门经理审核通过
在这里插入图片描述
在这里插入图片描述
王美美查看部门经理审核结果
在这里插入图片描述

部门经理审核通过,需要总经理审核(8级)登录,首页消息通知审核通过
首页系统通知
在这里插入图片描述
审批通过
在这里插入图片描述
总经理审核通过,王美美查看审核结果
在这里插入图片描述
如果部门经理审核不通过,则总经理不需要处理也没有系统通知
在这里插入图片描述

在这里插入图片描述

登录页面
login.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>慕课网OA办公系统</title><!-- 引入样式 --><link rel="stylesheet" type="text/css" href="assets/element-plus/index.css"><!-- 引入组件库 --><script src="/assets/vue/vue.global.js"></script><script src="/assets/element-plus/index.full.js"></script><script src="/assets/axios/axios.js"></script><style>.login-box {border: 1px solid #DCDFE6;width: 350px;margin: 180px auto;padding: 35px 35px 15px 35px;border-radius: 5px;-webkit-border-radius: 5px;-moz-border-radius: 5px;box-shadow: 0 0 25px #909399;}.login-title{text-align: center;margin: 0 auto 40px auto;color: #303133;}</style>
</head>
<body>
<div id="app"><el-form ref="loginForm" label-width="80px" :rules="rules" :model="form" class="login-box"><h2 class="login-title">慕课网OA办公系统</h2><el-form-item label="账号" prop="username"><el-input type="text" placeholder="请输入账号" v-model="form.username"></el-input></el-form-item><el-form-item label="密码" prop="password"><el-input type="password" placeholder="请输入密码" v-model="form.password"></el-input></el-form-item><el-form-item><el-button type="primary" v-on:click="onSubmit('loginForm')" style="width:200px">登录</el-button></el-form-item></el-form>
</div>
<script>const Main = {data() {return {form: {username: '',password: ''},rules:{username: [{required: true,message : '账号不能为空' , trigger:'blur'}],password:[{required: true,message : '密码不能为空' , trigger:'blur'}]}}},methods : {onSubmit(formName){const form = this.$refs[formName];form.validate((valid) => {if(valid){console.info("表单校验成功,准备提交数据");const form = this.form;const $message=this.$message;const params=new URLSearchParams();params.append("username",form.username);params.append("password",form.password);axios.post("/api/login",params,{}).then(function(response){console.info(response);const json=response.data;if(json.code==0){sessionStorage.uid=json.data.user.userId;sessionStorage.eid=json.data.user.employeeId;window.location.href="/index.html"}else{$message.error({message:json.message,offset:100});}})}})}}};//初始化Vue,绑定Main中的数据,利用ElementPlus对#app容器进行重新渲染const app = Vue.createApp(Main);app.use(ElementPlus);app.mount("#app");
</script>
</body>
</html>

首页
index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>慕课网办公OA系统</title><!-- 引入样式 --><link rel="stylesheet" type="text/css" href="assets/element-plus/index.css"><!-- 引入组件库 --><script src="/assets/vue/vue.global.js"></script><script src="/assets/element-plus/index.full.js"></script><script src="/assets/axios/axios.js"></script><style>.el-header {background-color: rgb(238, 241, 246);color: #333;line-height: 60px;}html,body,#app,.el-container {padding: 0px;margin: 0px;height: 100%;max-height: 100%;}</style>
</head>
<body><div id="app"><el-container style="height:100%;border:1px solid #eee"><el-header><el-row><el-col :span="12"><span style="font-size: 18px;color:darkcyan">慕课网办公OA系统</span></el-col><el-col :span="12" style="text-align:right"><el-dropdown><i class="el-icon-s-check" style="font-size:18px;margin-right: 15px"><span style="margin-right: 15px">{{employee.name}}[{{employee.title}}]</span></i><template #dropdown><el-dropdown-menu><el-dropdown-item v-on:click="logout">退出</el-dropdown-item></el-dropdown-menu></template></el-dropdown></el-col></el-row></el-header><el-container><el-aside width="200px" style="max-height:100%;background-color: rgb(238, 241, 246)"><!--默认展开第一个模块功能--><el-menu :default-openeds="['0']"><template v-for="(n,idx) in nodeList"><el-submenu :index="idx.toString()"><template #title><i class="el-icon-s-tools"></i>{{n.node.nodeName}}</template><template v-for="func in n.children"><el-menu-item :index="func.nodeId.toString()" v-on:click="showPage(func.url)">{{func.nodeName}}</el-menu-item></template></el-submenu></template></el-menu></el-aside><el-main><iframe id="main" name="main" src="/notice.html" style="width:100%;height:100%;border: 0px"></iframe></el-main></el-container></el-container></div><script>const Main = {data(){return {nodeList:[],employee:{}}},methods:{showPage(url){document.getElementById("main").src = url;},logout(){sessionStorage.clear();window.location.href = "/login.html";}},mounted(){const objApp = this;const eid = sessionStorage.eid;const uid = sessionStorage.uid;axios.get("/api/user_info?uid=" + uid + "&eid=" + eid).then(function(response){const json = response.data;json.data.nodeList.forEach(function (item){objApp.nodeList.push(item);})console.info(objApp.nodeList);objApp.employee = json.data.employee;})}};const app = Vue.createApp(Main);app.use(ElementPlus);app.mount("#app");</script>
</body>
</html>

请假申请页面
leave_form.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>请假申请单</title><!-- 引入样式 --><link rel="stylesheet" type="text/css" href="/assets/element-plus/index.css"><!-- 引入组件库 --><script src="/assets/vue/vue.global.js"></script><script src="/assets/element-plus/index.full.js"></script><script src="/assets/element-plus/locale/zh-cn.js"></script><script src="/assets/axios/axios.js"></script><style>.el-form {border: 1px solid #DCDFE6;width: 600px;margin: 180px auto;padding: 35px 35px 15px 35px;border-radius: 5px;-webkit-border-radius: 5px;-moz-border-radius: 5px;box-shadow: 0 0 25px #909399;}</style></head>
<body>
<div id="app"><el-form ref="leaveForm" :model="form" :rules="rules" label-width="80px"><el-descriptions title="请假申请单" :column="1" border><el-descriptions-item label="部门">{{department.departmentName}}</el-descriptions-item><el-descriptions-item label="申请人">{{employee.name}}[{{employee.title}}]</el-descriptions-item><el-descriptions-item label="请假类型"><el-select v-model="form.formType" style="width: 100%"><el-option label="事假" value="1"></el-option><el-option label="病假" value="2"></el-option><el-option label="工伤假" value="3"></el-option><el-option label="婚嫁" value="4"></el-option><el-option label="产假" value="5"></el-option><el-option label="丧假" value="6"></el-option></el-select></el-descriptions-item><el-descriptions-item label="请假时间"><el-form-item prop="timeRange" label-width="0px"><div class="block"><el-date-pickerv-model="form.timeRange"type="datetimerange"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期"@change="changeTimeRange"></el-date-picker></div></el-form-item></el-descriptions-item><el-descriptions-item label="请假原因"><el-form-item prop="reason" label-width="0px"><el-input type="text" placeholder="请输入请假原因" v-model="form.reason"/></el-form-item></el-descriptions-item></el-descriptions><div style="text-align: center;padding-top: 30px"><el-button type="primary" v-on:click="onSubmit('leaveForm')" >立即申请</el-button></div></el-form></div><script>var Main = {data() {return {employee:{},department:{},form: {formType: "1",timeRange: "",startTime: "",endTime: "",reason: "",eid: ""},// 表单验证,需要在 el-form-item 元素中增加 prop 属性rules: {timeRange: [{required: true, message: '请选择请假时间', trigger: 'blur'}],reason: [{required: true, message: '请填写请假原因', trigger: 'blur'}]}}},methods:{changeTimeRange : function(){console.info(this.form.timeRange);this.form.startTime = this.form.timeRange[0].getTime();this.form.endTime = this.form.timeRange[1].getTime();},onSubmit(formName){const objApp = this;const formData = this.form;const $message = this.$message;this.$refs[formName].validate(function(valid){if(valid){const params = new URLSearchParams();params.append("formType", formData.formType);params.append("startTime", formData.startTime);params.append("endTime", formData.endTime);params.append("reason", formData.reason);params.append("eid", sessionStorage.eid);axios.post("/api/leave/create",params).then(function(response){console.info(response);const json = response.data;if(json.code == "0"){objApp.$alert("请假单已提交,等待上级审批",{callback:function(){window.location.href = "/notice.html";}})}else{$message.error({message:json.message,offset:100})}})}})}},mounted(){const objApp = this;axios.get("/api/user_info?uid=" + sessionStorage.uid + "&eid=" + sessionStorage.eid).then(function(response){console.info(response);objApp.employee = response.data.data.employee;objApp.department = response.data.data.department;})}};ElementPlus.locale(ElementPlus.lang.zhCn);const app = Vue.createApp(Main);app.use(ElementPlus, ElementPlus.lang.zhCn);app.mount("#app");
</script>
</body>
</html>

请假审核页面
audit.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><!-- 引入样式 --><link rel="stylesheet" type="text/css" href="/assets/element-plus/index.css"><!-- 引入组件库 --><script src="/assets/vue/vue.global.js"></script><script src="/assets/element-plus/index.full.js"></script><script src="/assets/axios/axios.js"></script><style >.info .el-col,.info .el-select ,.info .el-input{padding-top: 5px;padding-bottom: 5px;}</style>
</head>
<body>
<div id="app"><h2>请假审批</h2><el-tableref="singleTable":data="tableData"highlight-current-row@current-change="handleCurrentChange"style="width: 100%"><el-table-columntype="index"width="50"></el-table-column><el-table-columnproperty="ctime"label="申请时间"width="180"></el-table-column><el-table-columnproperty="ftype"label="类型"width="120"></el-table-column><el-table-columnproperty="department_name"label="部门"width="120"></el-table-column><el-table-columnproperty="name"label="员工"width="120"></el-table-column><el-table-columnproperty="stime"label="起始时间"width="180"></el-table-column><el-table-columnproperty="etime"label="结束时间"width="180"></el-table-column><el-table-columnproperty="reason"label="请假原因"></el-table-column></el-table><el-dialog title="请假审批" v-model="dialogFormVisible" width="500px" center><el-descriptions  :column="2" border><el-descriptions-item label="部门">{{currentRow.department_name}}</el-descriptions-item><el-descriptions-item label="姓名">{{currentRow.name}}</el-descriptions-item><el-descriptions-item label="起始时间" >{{currentRow.stime}}</el-descriptions-item><el-descriptions-item label="结束时间" >{{currentRow.etime}}</el-descriptions-item><el-descriptions-item label="请假原因" :span="2">{{currentRow.reason}}</el-descriptions-item></el-descriptions><div class="info" ><el-form :model="form" ref="auditForm"><el-select v-model="form.result" placeholder="是否同意" style="width: 100%"><el-option label="同意" value="approved"></el-option><el-option label="驳回" value="refused"></el-option></el-select><el-input v-model="form.reason" placeholder="请输入审批意见" autocomplete="off"></el-input></el-form><span class="dialog-footer"><el-button type="primary" v-on:click="onSubmit('auditForm')" style="width: 100%">确认提交</el-button></span></div></el-dialog>
</div><script>function formatDate(time){var newDate = new Date(time);return newDate.getFullYear() + "-" +(newDate.getMonth() + 1) + "-" + newDate.getDate()+ " " + newDate.getHours() + "时";}var Main = {data() {return {dialogFormVisible: false,form: {result:"approved",reason:""},formLabelWidth: '120px',tableData: [{ctime:"2021-5-29 18时",ftype:"事假",stime:"2021-5-31 0时",etime:"2021-6-3 0时",department_name:"研发部",name:"王美美",reason:"测试数据"}],currentRow: null}},methods: {handleCurrentChange(val) {this.currentRow = val;console.info(val);this.dialogFormVisible = true;},onSubmit(formName){const objApp = this;this.$refs[formName].validate(function(valid){if(valid){const params = new URLSearchParams();params.append("formId", objApp.currentRow.form_id);params.append("result", objApp.form.result);params.append("reason", objApp.form.reason);params.append("eid", sessionStorage.eid);axios.post("/api/leave/audit" , params).then(function(response){const json = response.data;console.info(json);if(json.code=="0"){objApp.$alert("请假已审批完毕" , {callback:function(){window.location.href = "/notice.html";}})}else{objApp.$message.error({message:json.message,offset:100})}})}})}},mounted(){const objApp = this;const $message = this.$message;axios.get("/api/leave/list?eid=" + sessionStorage.eid).then(function(response){const json = response.data;if(json.code == '0'){objApp.tableData.splice(0, objApp.tableData.length);const formList = json.data.list;formList.forEach(function(item){switch (item.form_type){case 1:item.ftype = "事假";break;case 2:item.ftype = "病假";break;case 3:item.ftype = "工伤假";break;case 4:item.ftype = "婚假";break;case 5:item.ftype = "产假";break;case 6:item.ftype = "丧假";break;}item.stime = formatDate(item.start_time);item.etime = formatDate(item.end_time);item.ctime = formatDate(item.create_time);objApp.tableData.push(item);})}else{$message.error({message:json.message,offset:100})}})}};const app = Vue.createApp(Main);app.use(ElementPlus);app.mount("#app")
</script></body>
</html>

消息页面
notice.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>系统通知</title><!-- 引入样式 --><link rel="stylesheet" type="text/css" href="/assets/element-plus/index.css"><!-- 引入组件库 --><script src="/assets/vue/vue.global.js"></script><script src="/assets/element-plus/index.full.js"></script><script src="/assets/axios/axios.js"></script><script src="/assets/oa/security.js"></script>
</head>
<body>
<div id="app"><h2>系统通知</h2><el-tableref="singleTable":data="tableData"highlight-current-rowstyle="width: 100%"><el-table-columnproperty="index"label="序号"width="50"></el-table-column><el-table-columnproperty="ctime"label="通知时间"width="180"></el-table-column><el-table-columnproperty="content"label="通知内容"></el-table-column></el-table></div><script>var Main = {data() {return {tableData: []}},mounted() {const objApp = this;axios.get("/api/notice/list?eid=" + sessionStorage.eid).then(function (response) {objApp.tableData.splice(0, objApp.tableData.length);response.data.data.list.forEach(function (item,index) {var date = new Date(item.createTime);item.ctime = date.getFullYear() + "-" +(date.getMonth() + 1) + "-" + date.getDate()+ " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();item.index = index + 1;objApp.tableData.push(item);});}).catch(function (error) {console.log(error);});}};const app = Vue.createApp(Main);app.use(ElementPlus);app.mount("#app")
</script></body>
</html>

这篇关于rbac权限和多级请假设计的流程演示和前端页面实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/976478

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象