请假审批功能
实现待审批请假单列表
打开leave_form.xml,编写根据审批人和状态获取审批信息:
<select id="selectByParams" parameterType="java.util.Map" resultType="java.util.Map">
select f.* ,e.name , d.*
from
adm_leave_form f,adm_process_flow pf , adm_employee e , adm_department d
where
f.form_id = pf.form_id
and f.employee_id = e.employee_id
and e.department_id = d.department_id
and pf.state = #{pf_state} and pf.operator_id = #{pf_operator_id}
</select>
然后打开LeaveFormDao接口,把相应的方法编写:
public List<Map> selectByParams(@Param("pf_state") String pfState , @Param("pf_operator_id") Long operatorId);
然后打开LeaveFormService,把业务功能实现:
/**
* 获取指定任务状态及指定经办人对应的请假单列表
* @param pfState ProcessFlow任务状态
* @param operatorId 经办人编号
* @return 请假单及相关数据列表
*/
public List<Map> getLeaveFormList(String pfState , Long operatorId){
return (List<Map>)MyBatisUtils.executeQuery(sqlSession -> {
LeaveFormDao dao = sqlSession.getMapper(LeaveFormDao.class);
List<Map> formList = dao.selectByParams(pfState, operatorId);
return formList;
});
}
然后打开LeaveFormServlet,编写相应请求相应方法,并把返回数据按lay-ui数据表格格式要求封装成JSON字符串返回:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// http://localhost/leave/create
String uri = request.getRequestURI();
String methodName = uri.substring(uri.lastIndexOf("/")+1);
if(methodName.equals("create")){
this.create(request,response);
}else if(methodName.equals("list")){
this.getLeaveFormList(request, response);
}
}
/**
* 查询需要审核的请假单列表
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
private void getLeaveFormList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User user = (User)request.getSession().getAttribute("login_user");
List<Map> formList = leaveFormService.getLeaveFormList("process", user.getEmployeeId());
Map result = new HashMap();
result.put("code", "0");
result.put("msg", "");
result.put("count", formList.size());
result.put("data", formList);
String json = JSON.toJSONString(result);
response.getWriter().println(json);
}
最后在src/main/webapp/WEB-INF/ftl路径下创建audit.ftl请假审批列表页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>请假审批</title>
<link rel="stylesheet" href="/resources/layui/css/layui.css">
<style>
.form-item{
padding: 10px;
}
.form-item-value{
padding: 10px;
}
</style>
</head>
<body>
<div class="layui-row">
<blockquote class="layui-elem-quote">
<h1>请假审批</h1>
</blockquote>
<!--待审批列表-->
<table id="grdFormList" lay-filter="grdFormList"></table>
</div>
<!--请假详情对话框-->
<div id="divDialog" style="display: none;padding: 10px">
<form class="layui-form">
<div class="layui-form-item">
<div class="layui-row">
<div class="layui-col-xs2 form-item">部门</div>
<div class="layui-col-xs4 form-item-value" id="dname"></div>
<div class="layui-col-xs2 form-item">姓名</div>
<div class="layui-col-xs4 form-item-value" id="name"></div>
</div>
<div class="layui-row">
<div class="layui-col-xs2 form-item">起始时间</div>
<div class="layui-col-xs4 form-item-value" id="startTime"></div>
<div class="layui-col-xs2 form-item">结束时间</div>
<div class="layui-col-xs4 form-item-value" id="endTime"></div>
</div>
<div class="layui-row">
<div class="layui-col-xs2 form-item">请假原因</div>
<div class="layui-col-xs10 form-item-value" id="reason"></div>
</div>
<!--表单Id-->
<input type="hidden" name="formId" id="formId">
<!--审批结果-->
<select name="result" lay-verfity="required">
<option value="approved">同意</option>
<option value="refused">驳回</option>
</select>
</div>
<div class="layui-form-item">
<!--审批意见-->
<input type="text" name="reason" placeholder="请输入审批意见"
autocomplete="off" class="layui-input"/>
</div>
<div class="layui-form-item">
<button class="layui-btn layui-btn-fluid " lay-submit lay-filter="audit">确认提交</button>
</div>
</form>
</div>
<script src="/resources/layui/layui.js"></script>
<script src="/resources/sweetalert2.all.min.js"></script>
<script>
var $ = layui.$;
//将毫秒数转换为"yyyy-MM-dd HH时"字符串格式
function formatDate(time){
var newDate = new Date(time);
return newDate.getFullYear() + "-" +
(newDate.getMonth() + 1) + "-" + newDate.getDate()
+ " " + newDate.getHours() + "时";
}
// 将table渲染为数据表格
layui.table.render({
elem : "#grdFormList" , //选择器
id : "grdFormList" , //id
url : "/leave/list" , //ajax请求url
page : false , //是否分页 true-是 false-否
cols :[[ //列描述
{title : "" , width:70 , style : "height:60px" , type:"numbers"}, // numbers代表序号列
{field : "create_time" , title : "申请时间" , width : 150 , templet: function (d) {
//templet代表对数据进行加工后再显示
return formatDate(d.create_time)
}},
{field : "form_type" , title : "类型" , width : 100 , templet: function(d){
switch (d.form_type) {
case 1:
return "事假";
case 2:
return "病假";
case 3:
return "工伤假";
case 4:
return "婚假";
case 5:
return "产假";
case 6:
return "丧假";
}
}},
{field : "department_name" , title : "部门" , width : 100},
{field : "name" , title : "员工" , width : 100},
{field : "start_time" , title : "起始时间" , width : 150, templet: function (d) {
return formatDate(d.start_time)
}},
{field : "end_time" , title : "结束时间" , width : 150 , templet: function (d) {
return formatDate(d.end_time)
}},
{field : "reason" , title : "请假原因" , width : 350 },
{title : "" , width:150 ,type:"space" , templet : function(d){
var strRec = JSON.stringify(d);
console.info("请假单数据", d);
console.info("请假单数据", strRec);
//将请假单数据存放至data-laf属性中
return "<button class='layui-btn layui-btn-danger layui-btn-sm btn-audit' data-laf=" + strRec + " >审批</button>";
}}
]]
})
// 绑定每一行的审批按钮
$(document).on("click" , ".btn-audit" , function(){
//初始化表单
$("#divDialog form")[0].reset();
$("#divDialog form form-item-value").text("");
//获取当前点击按钮的请假单数据,回填至显示项
var laf = $(this).data("laf");
$("#dname").text(laf.department_name);
$("#name").text(laf.name);
$("#startTime").text(formatDate(laf.start_time));
$("#endTime").text(formatDate(laf.end_time));
$("#reason").text(laf.reason);
$("#formId").val(laf.form_id);
//弹出layui对话框
layui.layer.open({
type : "1" , //页面层
title : "请假审批" , //标题
content : $("#divDialog") , //指定对话框容器对象
area : ["500px" , "400px"] , //尺寸
end : function(){ //销毁后触发事件
$("#divDialog").hide();
}
})
})
/**
* 提交审批数据
*/
layui.form.on("submit(audit)" , function(data){
$.ajax({
url : "/leave/audit", //审核URL
data : data.field ,
type : "post" ,
dataType : "json" ,
success: function (json) {
//关闭所有layui对话框
layui.layer.closeAll();
//显示处理结果
if(json.code == "0"){
swal({
type: 'success',
html: "<h2>请假已审批完毕</h2>",
confirmButtonText: "确定"
}).then(function (result) {
window.location.href="/forward/notice";
});
}else{
swal({
type: 'warning',
html: "<h2>" + json.message + "</h2>",
confirmButtonText: "确定"
});
}
}
})
return false;
})
</script>
</body>
</html>
实现审批业务逻辑
打开process_flow.xml文件,添加更新流程表和根据表单id获取流程数据的sql
<update id="update" parameterType="com.ql.oa.entity.ProcessFlow">
UPDATE adm_process_flow SET form_id = #{formId}, operator_id = #{operatorId}, action = #{action}, result = #{result}, reason = #{reason}, create_time = #{createTime}, audit_time = #{auditTime}, order_no = #{orderNo}, state = #{state}, is_last = #{isLast}
WHERE process_id = #{processId}
</update>
<select id="selectByFormId" parameterType="Long" resultType="com.ql.oa.entity.ProcessFlow">
select * from adm_process_flow where form_id = #{value} order by order_no
</select>
然后打开ProcessFlowDao接口将把两个方法声明加上
public void update(ProcessFlow processFlow);
public List<ProcessFlow> selectByFormId(Long formId);
打开leave_form.xml文件,添加更新表单和根据id获取表单的sql
<select id="selectById" parameterType="Long" resultType="com.ql.oa.entity.LeaveForm">
select * from adm_leave_form where form_id = #{value}
</select>
<update id="update" parameterType="com.ql.oa.entity.LeaveForm">
UPDATE adm_leave_form SET employee_id = #{employeeId} , form_type = #{formType}, start_time = #{startTime}, end_time = #{endTime}, reason = #{reason}, state = #{state} ,create_time = #{createTime} WHERE form_id = #{formId}
</update>
然后打开LeaveFormDao接口将把两个方法声明加上
public LeaveForm selectById(Long formId);
public void update(LeaveForm form);
准备工作做好后开始编写审批业务逻辑,打开LeaveFormService编写审批逻辑:
/**
* 审核请假单
* @param formId 表单编号
* @param operatorId 经办人(当前登录员工)
* @param result 审批结果
* @param reason 审批意见
*/
public void audit(Long formId , Long operatorId , String result , String reason){
MyBatisUtils.executeUpdate(sqlSession -> {
//1.无论同意/驳回,当前任务状态变更为complete
ProcessFlowDao processFlowDao = sqlSession.getMapper(ProcessFlowDao.class);
List<ProcessFlow> flowList = processFlowDao.selectByFormId(formId);
if(flowList.size() == 0){
throw new BussinessException("PF001", "无效的审批流程");
}
//获取当前任务ProcessFlow对象
List<ProcessFlow> processList = flowList.stream().filter(p -> p.getOperatorId() == operatorId && p.getState().equals("process")).collect(Collectors.toList());
ProcessFlow process = null;
if(processList.size()==0){
throw new BussinessException("PF002", "未找到待处理任务");
}else{
process = processList.get(0);
process.setState("complete");
process.setResult(result);
process.setReason(reason);
process.setAuditTime(new Date());
processFlowDao.update(process);
}
LeaveFormDao leaveFormDao = sqlSession.getMapper(LeaveFormDao.class);
LeaveForm form = leaveFormDao.selectById(formId);
//2.如果当前任务是最后一个节点,代表流程结束,更新请假单状态为对应的approved/refused
if(process.getIsLast() == 1){
form.setState(result);//approved|refused
leaveFormDao.update(form);
}else{
//readyList包含所有后续任务节点
List<ProcessFlow> readyList = flowList.stream().filter(p -> p.getState().equals("ready")).collect(Collectors.toList());
//3.如果当前任务不是最后一个节点且审批通过,那下一个节点的状态从ready变为process
if(result.equals("approved")){
ProcessFlow readyProcess = readyList.get(0);
readyProcess.setState("process");
processFlowDao.update(readyProcess);
}else if(result.equals("refused")) {
//4.如果当前任务不是最后一个节点且审批驳回,则后续所有任务状态变为cancel,请假单状态变为refused
for(ProcessFlow p:readyList){
p.setState("cancel");
processFlowDao.update(p);
}
form.setState("refused");
leaveFormDao.update(form);
}
}
return null;
});
}
完整实现请假审批
根据audit.ftl中的审批提交js
/**
* 提交审批数据
*/
layui.form.on("submit(audit)" , function(data){
$.ajax({
url : "/leave/audit", //审核URL
data : data.field ,
type : "post" ,
dataType : "json" ,
success: function (json) {
//关闭所有layui对话框
layui.layer.closeAll();
//显示处理结果
if(json.code == "0"){
swal({
type: 'success',
html: "<h2>请假已审批完毕</h2>",
confirmButtonText: "确定"
}).then(function (result) {
window.location.href="/forward/notice";
});
}else{
swal({
type: 'warning',
html: "<h2>" + json.message + "</h2>",
confirmButtonText: "确定"
});
}
}
})
return false;
})
编写处理提交审批的servlet,打开LeaveFormServlet,添加处理提交审批的方法并在doPost方法里调用
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// http://localhost/leave/create
String uri = request.getRequestURI();
String methodName = uri.substring(uri.lastIndexOf("/")+1);
if(methodName.equals("create")){
this.create(request,response);
}else if(methodName.equals("list")){
this.getLeaveFormList(request, response);
}else if(methodName.equals("audit")){
this.audit(request, response);
}
}
/**
* 处理审批操作
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
private void audit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String formId = request.getParameter("formId");
String result = request.getParameter("result");
String reason = request.getParameter("reason");
User user = (User)request.getSession().getAttribute("login_user");
Map mpResult = new HashMap();
try {
leaveFormService.audit(Long.parseLong(formId), user.getEmployeeId(), result, reason);
mpResult.put("code", "0");
mpResult.put("message", "success");
}catch(Exception e){
logger.error("请假单审核失败",e);
mpResult.put("code", e.getClass().getSimpleName());
mpResult.put("message", e.getMessage());
}
String json = JSON.toJSONString(mpResult);
response.getWriter().println(json);
}
运行项目做审批测试。
开发系统通知功能
实现系统消息业务逻辑
打开Notice.java实体类,添加两个构造方法来简化消息提醒创建
public Notice(){
}
public Notice(Long receiverId , String content){
this.receiverId = receiverId;
this.content = content;
this.createTime = new Date();
}
然后打开LeaveFormService分别在创建请假单、审批请假单业务逻辑中添加相应的消息通知
package com.ql.oa.service;
import com.ql.oa.dao.EmployeeDao;
import com.ql.oa.dao.LeaveFormDao;
import com.ql.oa.dao.NoticeDao;
import com.ql.oa.dao.ProcessFlowDao;
import com.ql.oa.entity.Employee;
import com.ql.oa.entity.LeaveForm;
import com.ql.oa.entity.Notice;
import com.ql.oa.entity.ProcessFlow;
import com.ql.oa.service.exception.BussinessException;
import com.ql.oa.utils.MyBatisUtils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 请假单流程服务
*/
public class LeaveFormService {
/**
* 创建请假单
* @param form 前端输入的请假单数据
* @return 持久化后的请假单对象
*/
public LeaveForm createLeaveForm(LeaveForm form){
LeaveForm savedForm = (LeaveForm)MyBatisUtils.executeUpdate(sqlSession -> {
//1.持久化form表单数据,8级以下员工表单状态为processing,8级(总经理)状态为approved
EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
Employee employee = employeeDao.selectById(form.getEmployeeId());
if(employee.getLevel() == 8){
form.setState("approved");
}else{
form.setState("processing");
}
LeaveFormDao leaveFormDao = sqlSession.getMapper(LeaveFormDao.class);
leaveFormDao.insert(form);
//2.增加第一条流程数据,说明表单已提交,状态为complete
ProcessFlowDao processFlowDao = sqlSession.getMapper(ProcessFlowDao.class);
ProcessFlow flow1 = new ProcessFlow();
flow1.setFormId(form.getFormId());
flow1.setOperatorId(employee.getEmployeeId());
flow1.setAction("apply");
flow1.setCreateTime(new Date());
flow1.setOrderNo(1);
flow1.setState("complete");
flow1.setIsLast(0);
processFlowDao.insert(flow1);
//3.分情况创建其余流程数据
//3.1 7级以下员工,生成部门经理审批任务,请假时间大于72小时,还需生成总经理审批任务
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH时");
NoticeDao noticeDao = sqlSession.getMapper(NoticeDao.class);
if(employee.getLevel() < 7){
Employee dmanager = employeeDao.selectLeader(employee);
ProcessFlow flow2 = new ProcessFlow();
flow2.setFormId(form.getFormId());
flow2.setOperatorId(dmanager.getEmployeeId());
flow2.setAction("audit");
flow2.setCreateTime(new Date());
flow2.setOrderNo(2);
flow2.setState("process");
long diff = form.getEndTime().getTime() - form.getStartTime().getTime();
float hours = diff/(1000*60*60) * 1f;
if(hours >= BussinessConstants.MANAGER_AUDIT_HOURS){
flow2.setIsLast(0);
processFlowDao.insert(flow2);
Employee manager = employeeDao.selectLeader(dmanager);
ProcessFlow flow3 = new ProcessFlow();
flow3.setFormId(form.getFormId());
flow3.setOperatorId(manager.getEmployeeId());
flow3.setAction("audit");
flow3.setCreateTime(new Date());
flow3.setState("ready");
flow3.setOrderNo(3);
flow3.setIsLast(1);
processFlowDao.insert(flow3);
}else {
flow2.setIsLast(1);
processFlowDao.insert(flow2);
}
//请假单已提交消息
String noticeContent = String.format("您的请假申请[%s-%s]已提交,请等待上级审批."
, sdf.format(form.getStartTime()), sdf.format(form.getEndTime()));
noticeDao.insert(new Notice(employee.getEmployeeId(),noticeContent));
//通知部门经理审批消息
noticeContent = String.format("%s-%s提起请假申请[%s-%s],请尽快审批",
employee.getTitle() , employee.getName() ,sdf.format(form.getStartTime()),sdf.format(form.getEndTime()));
noticeDao.insert(new Notice(dmanager.getEmployeeId(),noticeContent));
}else if(employee.getLevel() == 7){ //部门经理
//3.2 7级员工,生成总经理审批任务
Employee manager = employeeDao.selectLeader(employee);
ProcessFlow flow = new ProcessFlow();
flow.setFormId(form.getFormId());
flow.setOperatorId(manager.getEmployeeId());
flow.setAction("audit");
flow.setCreateTime(new Date());
flow.setState("process");
flow.setOrderNo(2);
flow.setIsLast(1);
processFlowDao.insert(flow);
//请假单已提交消息
String noticeContent = String.format("您的请假申请[%s-%s]已提交,请等待上级审批."
, sdf.format(form.getStartTime()), sdf.format(form.getEndTime()));
noticeDao.insert(new Notice(employee.getEmployeeId(),noticeContent));
//通知总经理审批消息
noticeContent = String.format("%s-%s提起请假申请[%s-%s],请尽快审批",
employee.getTitle() , employee.getName() ,sdf.format(form.getStartTime()),sdf.format(form.getEndTime()));
noticeDao.insert(new Notice(manager.getEmployeeId(),noticeContent));
}else if(employee.getLevel() == 8){
//3.3 8级员工,生成总经理审批任务,系统自动通过
ProcessFlow flow = new ProcessFlow();
flow.setFormId(form.getFormId());
flow.setOperatorId(employee.getEmployeeId());
flow.setAction("audit");
flow.setResult("approved");
flow.setReason("自动通过");
flow.setCreateTime(new Date());
flow.setAuditTime(new Date());
flow.setState("complete");
flow.setOrderNo(2);
flow.setIsLast(1);
processFlowDao.insert(flow);
String noticeContent = String.format("您的请假申请[%s-%s]系统已自动批准通过." ,
sdf.format(form.getStartTime()) , sdf.format(form.getEndTime()));
noticeDao.insert(new Notice(employee.getEmployeeId(),noticeContent));
}
return form;
});
return savedForm;
}
/**
* 获取指定任务状态及指定经办人对应的请假单列表
* @param pfState ProcessFlow任务状态
* @param operatorId 经办人编号
* @return 请假单及相关数据列表
*/
public List<Map> getLeaveFormList(String pfState , Long operatorId){
return (List<Map>)MyBatisUtils.executeQuery(sqlSession -> {
LeaveFormDao dao = sqlSession.getMapper(LeaveFormDao.class);
List<Map> formList = dao.selectByParams(pfState, operatorId);
return formList;
});
}
/**
* 审核请假单
* @param formId 表单编号
* @param operatorId 经办人(当前登录员工)
* @param result 审批结果
* @param reason 审批意见
*/
public void audit(Long formId , Long operatorId , String result , String reason){
MyBatisUtils.executeUpdate(sqlSession -> {
//1.无论同意/驳回,当前任务状态变更为complete
ProcessFlowDao processFlowDao = sqlSession.getMapper(ProcessFlowDao.class);
List<ProcessFlow> flowList = processFlowDao.selectByFormId(formId);
if(flowList.size() == 0){
throw new BussinessException("PF001", "无效的审批流程");
}
//获取当前任务ProcessFlow对象
List<ProcessFlow> processList = flowList.stream().filter(p -> p.getOperatorId() == operatorId && p.getState().equals("process")).collect(Collectors.toList());
ProcessFlow process = null;
if(processList.size()==0){
throw new BussinessException("PF002", "未找到待处理任务");
}else{
process = processList.get(0);
process.setState("complete");
process.setResult(result);
process.setReason(reason);
process.setAuditTime(new Date());
processFlowDao.update(process);
}
LeaveFormDao leaveFormDao = sqlSession.getMapper(LeaveFormDao.class);
LeaveForm form = leaveFormDao.selectById(formId);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH时");
EmployeeDao employeeDao = sqlSession.getMapper(EmployeeDao.class);
Employee employee = employeeDao.selectById(form.getEmployeeId());//表单提交人信息
Employee operator = employeeDao.selectById(operatorId);//任务经办人信息
NoticeDao noticeDao = sqlSession.getMapper(NoticeDao.class);
//2.如果当前任务是最后一个节点,代表流程结束,更新请假单状态为对应的approved/refused
if(process.getIsLast() == 1){
form.setState(result);//approved|refused
leaveFormDao.update(form);
String strResult = null;
if(result.equals("approved")){
strResult = "批准";
}else if (result.equals("refused")){
strResult = "驳回";
}
String noticeContent = String.format("您的请假申请[%s-%s]%s%s已%s,审批意见:%s,审批流程已结束",
sdf.format(form.getStartTime()) , sdf.format(form.getEndTime()),
operator.getTitle(),operator.getName(),
strResult,reason);//发给表单提交人的通知
noticeDao.insert(new Notice(form.getEmployeeId(),noticeContent));
noticeContent = String.format("%s-%s提起请假申请[%s-%s]您已%s,审批意见:%s,审批流程已结束" ,
employee.getTitle() , employee.getName() , sdf.format( form.getStartTime()) , sdf.format(form.getEndTime()),
strResult , reason);//发给审批人的通知
noticeDao.insert(new Notice(operator.getEmployeeId(),noticeContent));
}else{
//readyList包含所有后续任务节点
List<ProcessFlow> readyList = flowList.stream().filter(p -> p.getState().equals("ready")).collect(Collectors.toList());
//3.如果当前任务不是最后一个节点且审批通过,那下一个节点的状态从ready变为process
if(result.equals("approved")){
ProcessFlow readyProcess = readyList.get(0);
readyProcess.setState("process");
processFlowDao.update(readyProcess);
//消息1: 通知表单提交人,部门经理已经审批通过,交由上级继续审批
String noticeContent1 = String.format("您的请假申请[%s-%s]%s%s已批准,审批意见:%s ,请继续等待上级审批" ,
sdf.format(form.getStartTime()) , sdf.format(form.getEndTime()),
operator.getTitle() , operator.getName(),reason);
noticeDao.insert(new Notice(form.getEmployeeId(),noticeContent1));
//消息2: 通知总经理有新的审批任务
String noticeContent2 = String.format("%s-%s提起请假申请[%s-%s],请尽快审批" ,
employee.getTitle() , employee.getName() , sdf.format( form.getStartTime()) , sdf.format(form.getEndTime()));
noticeDao.insert(new Notice(readyProcess.getOperatorId(),noticeContent2));
//消息3: 通知部门经理(当前经办人),员工的申请单你已批准,交由上级继续审批
String noticeContent3 = String.format("%s-%s提起请假申请[%s-%s]您已批准,审批意见:%s,申请转至上级领导继续审批" ,
employee.getTitle() , employee.getName() , sdf.format( form.getStartTime()) , sdf.format(form.getEndTime()), reason);
noticeDao.insert(new Notice(operator.getEmployeeId(),noticeContent3));
}else if(result.equals("refused")) {
//4.如果当前任务不是最后一个节点且审批驳回,则后续所有任务状态变为cancel,请假单状态变为refused
for(ProcessFlow p:readyList){
p.setState("cancel");
processFlowDao.update(p);
}
form.setState("refused");
leaveFormDao.update(form);
//消息1: 通知申请人表单已被驳回
String noticeContent1 = String.format("您的请假申请[%s-%s]%s%s已驳回,审批意见:%s,审批流程已结束" ,
sdf.format(form.getStartTime()) , sdf.format(form.getEndTime()),
operator.getTitle() , operator.getName(),reason);
noticeDao.insert(new Notice(form.getEmployeeId(),noticeContent1));
//消息2: 通知经办人表单"您已驳回"
String noticeContent2 = String.format("%s-%s提起请假申请[%s-%s]您已驳回,审批意见:%s,审批流程已结束" ,
employee.getTitle() , employee.getName() , sdf.format( form.getStartTime()) , sdf.format(form.getEndTime()), reason);
noticeDao.insert(new Notice(operator.getEmployeeId(),noticeContent2));
}
}
return null;
});
}
}
完整实现系统消息功能
打开notice.xml文件,添加根据接收人id查询消息提醒数据sql
<select id="selectByReceiverId" parameterType="Long" resultType="com.ql.oa.entity.Notice">
select * from sys_notice where receiver_id = #{value} order by create_time desc limit 0,100
</select>
打开NoticeDao接口相应的方法声明加上
public List<Notice> selectByReceiverId(Long receiverId);
在com.ql.oa.service包下创建NoticeService.java文件
package com.ql.oa.service;
import com.ql.oa.dao.NoticeDao;
import com.ql.oa.entity.Notice;
import com.ql.oa.utils.MyBatisUtils;
import java.util.List;
/**
* 消息服务
*/
public class NoticeService {
/**
* 查询指定员工的系统消息
* @param receiverId
* @return 最近100条消息列表
*/
public List<Notice> getNoticeList(Long receiverId){
return (List)MyBatisUtils.executeQuery(sqlSession -> {
NoticeDao noticeDao = sqlSession.getMapper(NoticeDao.class);
return noticeDao.selectByReceiverId(receiverId);
});
}
}
在com.ql.oa.controller包下创建NoticeServlet,编写获取消息提醒selvlet
package com.ql.oa.controller;
import com.alibaba.fastjson.JSON;
import com.ql.oa.entity.Notice;
import com.ql.oa.entity.User;
import com.ql.oa.service.NoticeService;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet(name = "NoticeServlet" , urlPatterns = "/notice/list")
public class NoticeServlet extends HttpServlet {
private NoticeService noticeService = new NoticeService();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User user = (User)request.getSession().getAttribute("login_user");
List<Notice> noticeList = noticeService.getNoticeList(user.getEmployeeId());
Map result = new HashMap<>();
result.put("code", "0");
result.put("msg", "");
result.put("count", noticeList.size());
result.put("data", noticeList);
String json = JSON.toJSONString(result);
response.setContentType("text/html;charset=utf-8");
response.getWriter().println(json);
}
}
然后src/main/webapp/WEB-INF/ftl路径下新建notice.ftl文件,编写消息提醒列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>系统通知</title>
<link rel="stylesheet" href="/resources/layui/css/layui.css">
</head>
<body>
<div class="layui-row">
<blockquote class="layui-elem-quote">
<h2>系统通知</h2>
</blockquote>
<table id="grdNoticeList" lay-filter="grdNoticeList"></table>
</div>
<script src="/resources/layui/layui.js"></script>
<script>
layui.table.render({
elem : "#grdNoticeList" ,
id : "grdNoticeList" ,
url : "/notice/list" ,
page : false ,
cols :[[
{field : "" , title : "序号" , width:"10%" , style : "height:60px" , type:"numbers"},
{field : "create_time" , title : "通知时间" , width : "20%" , templet: function (d) {
var newDate = new Date(d.createTime);
return newDate.getFullYear() + "-" +
(newDate.getMonth() + 1) + "-" + newDate.getDate()
+ " " + newDate.getHours() + ":" + newDate.getMinutes() + ":" + newDate.getSeconds();
}},
{field : "content" , title : "通知内容" , width : "60%"}
]]
})
</script>
</body>
</html>
最后打开index.ftl文件,配置主题部分默认打开消息提醒内容,iframe标签添加src属性
<!--主体部分采用iframe嵌入其他页面-->
<div class="layui-body" style="overflow-y: hidden">
<iframe name="ifmMain" src="/forward/notice" style="border: 0px;width: 100%;height: 100%"></iframe>
</div>
运行项目测试。