赞
踩
登录账号: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-picker v-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-table ref="singleTable" :data="tableData" highlight-current-row @current-change="handleCurrentChange" style="width: 100%"> <el-table-column type="index" width="50"> </el-table-column> <el-table-column property="ctime" label="申请时间" width="180"> </el-table-column> <el-table-column property="ftype" label="类型" width="120"> </el-table-column> <el-table-column property="department_name" label="部门" width="120"> </el-table-column> <el-table-column property="name" label="员工" width="120"> </el-table-column> <el-table-column property="stime" label="起始时间" width="180"> </el-table-column> <el-table-column property="etime" label="结束时间" width="180"> </el-table-column> <el-table-column property="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-table ref="singleTable" :data="tableData" highlight-current-row style="width: 100%"> <el-table-column property="index" label="序号" width="50"> </el-table-column> <el-table-column property="ctime" label="通知时间" width="180"> </el-table-column> <el-table-column property="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>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。