毕业设计实战:基于SSM的学生网上请假系统设计与实现全攻略

0 阅读13分钟

毕业设计实战:基于SSM的学生网上请假系统设计与实现全攻略

在开发“学生网上请假系统”这套毕设时,我曾因“请假流程与考勤管理脱节”踩过一个关键坑。初期设计时,我将“学生请假申请”和“考勤记录”视为两个独立的模块,导致学生请假获批后,考勤记录未自动同步更新,教师端看到的考勤状态与请假状态不一致,期末统计时数据混乱,耗费3天重构了请假与考勤的联动机制、引入请假状态机(待审核→班主任审核→系主任审核→通过/拒绝)和考勤自动更新逻辑才解决了问题📝。

基于此次实战经验,本文将精简拆解这套涵盖管理员、系主任、老师、学生四大角色的网上请假系统,分享核心开发流程与实操细节,为同类请假审批类毕设提供一份可落地的参考。

一、需求分析:聚焦“请假审批流程”核心,避免功能冗余

很多同学在做审批类系统时,容易陷入“功能堆砌”的误区。我最初也曾想加入一个复杂的“课程签到地图”模块,结果因偏离“请假申请、多级审批、考勤关联”等核心业务,被导师要求删减。

在做这套系统时,我的核心思路是抓住**“请假”这个事件主体,围绕“审批”这个场景,理清“学生(申请人)”“老师(班主任审批)”“系主任(最终审批)”“管理员(系统管理)”**之间的关系,最终形成 “学生提交请假 → 班主任初审 → 系主任终审 → 通过后自动更新考勤 → 学生查看审批结果” 的业务闭环。

1. 核心角色与功能(精简版)

角色核心功能
管理员系主任管理(增删改查/重置密码)、老师管理、学生管理、班级管理、课程管理、课表管理、公告管理
系主任请假管理(查看学生请假申请并终审)、学生管理、老师信息查看、考勤统计查看、课程查看、公告管理
老师(班主任)请假管理(初审学生的请假申请)、考勤管理(录入/修改学生考勤)、课程查看、学生信息查看
学生请假管理(提交请假申请/查看审批进度)、考勤查看、班级查看、课程查看、个人信息管理

2. 需求避坑要点

  • 拒绝空想,模拟流程:在开发前,我邀请了10名学生、3位班主任和2位系主任模拟了“学生因病请假→提交申请→班主任审批→系主任审批→通过后考勤自动更新→学生查看结果”的完整流程。发现学生最关心“审批进度”,于是增加了“审批状态跟踪(待班主任审核/待系主任审核/已通过/已拒绝)”功能。
  • 明确约束条件:提前规定“请假编号自动生成(格式:QJ+年月日+流水号)”“请假天数自动计算(根据开始日期和结束日期)”“请假通过后考勤状态自动更新为请假”“不同请假类型需不同证明材料”,这些明确的约束为后续系统实现提供了清晰的业务边界。

二、技术选型:稳定框架 + 多级审批,新手友好

这套系统涉及多级审批流程,前期我曾尝试使用工作流引擎,结果学习成本高且配置复杂。最终我回归了更简单直接的方案:

技术工具选型理由避坑提醒
SSM框架(Spring+SpringMVC+MyBatis)经典成熟的企业级开发框架,文档丰富,适合审批类系统的稳定开发重点掌握Spring声明式事务管理;请假审批涉及多表操作(请假单状态更新+考勤记录新增)必须加事务
JSP + JSTL + jQuery传统的服务端渲染方式,开发简单,适合毕设快速实现使用<c:if>标签根据审批状态显示不同按钮;表单提交用Ajax提升用户体验
MySQL 5.7存储所有业务数据请假表需要请假编号、请假类型、开始/结束日期、请假天数、审批状态等多个字段;考勤表需要关联学生和考勤状态
Bootstrap快速搭建响应式前端界面,适配PC端和移动端使用Bootstrap的模态框实现审批弹窗,方便填写审核意见

三、数据库设计:业务关联清晰,支撑审批闭环

数据库设计直接影响后续开发效率。前期因未设计“审批状态字段”和“考勤联动机制”,导致请假通过后考勤状态未更新、审批流程不可追溯。

1. 核心表结构(精选核心表)

  • 学生表(yonghu)idusername(学号)、passwordclazz_id(班级)、yonghu_uuid_number(学号)、yonghu_nameyonghu_phoneyonghu_id_numberyonghu_photosex_typesyonghu_email
  • 老师表(laoshi)idusernamepasswordlaoshi_uuid_number(工号)、laoshi_namelaoshi_phonelaoshi_id_numberlaoshi_photosex_typeslaoshi_email
  • 系主任表(xizhuren)idusernamepasswordxizhuren_uuid_number(工号)、xizhuren_namexizhuren_phonexizhuren_id_numberxizhuren_photosex_typesxizhuren_email
  • 班级表(clazz)idlaoshi_id(班主任)、clazz_nameclazz_address
  • 课程表(kecheng)idlaoshi_id(任课老师)、kecheng_namekecheng_addresskecheng_types(课程形式)。
  • 请假表(qingjia)这是核心业务表。包含qingjia_uuid_number(请假编号)、yonghu_id(学生)、qingjia_name(请假标题)、qingjia_types(请假类型)、qingjiakaishi_time(开始日期)、qingjia_number(请假天数)、qingjiajieshu_time(结束日期)、qingjia_content(请假内容)、insert_time(申请时间)、qingjia_yesno_types(审批状态:1待班主任审核/2待系主任审核/3已通过/4已拒绝)、qingjia_yesno_text(审核回复)、qingjia_shenhe_time(审核时间)。
  • 考勤表(kaoqin)idyonghu_id(学生)、kaoqin_types(考勤状态:正常/迟到/早退/旷课/请假)、kaoqin_time(考勤日期)、insert_time(录入时间)。
  • 公告表(gonggao)idgonggao_namegonggao_typesinsert_timegonggao_content

2. 关键业务SQL示例

示例SQL(查询学生的完整请假记录及审批进度):

-- 查询学生“张三”的所有请假记录及审批状态
SELECT 
    q.qingjia_uuid_number AS leave_no,
    q.qingjia_name AS title,
    q.qingjia_types AS leave_type,
    q.qingjiakaishi_time AS start_date,
    q.qingjiajieshu_time AS end_date,
    q.qingjia_number AS days,
    q.qingjia_content AS reason,
    q.insert_time AS apply_time,
    q.qingjia_yesno_types AS status,  -- 1待班主任/2待系主任/3已通过/4已拒绝
    q.qingjia_yesno_text AS reply,
    q.qingjia_shenhe_time AS audit_time,
    l.laoshi_name AS teacher_name,
    x.xizhuren_name AS director_name
FROM qingjia q
LEFT JOIN yonghu y ON q.yonghu_id = y.id
LEFT JOIN clazz c ON y.clazz_id = c.id
LEFT JOIN laoshi l ON c.laoshi_id = l.id
LEFT JOIN xizhuren x ON 1=1  -- 系主任固定,实际可根据业务关联
WHERE y.yonghu_name = '张三'
ORDER BY q.insert_time DESC;

关键避坑

  • 审批状态流转:请假单状态必须按顺序流转:待班主任审核(1)→待系主任审核(2)→已通过/已拒绝(3/4)。班主任审核通过后状态变为2,系主任审核通过后状态变为3。
  • 考勤自动更新:请假通过后,需在考勤表中自动插入对应日期的请假记录,标记为请假状态。
  • 数据一致性:涉及请假单状态更新和考勤记录插入的多表操作,务必使用事务注解 @Transactional

四、核心功能实现:6大模块满足答辩需求

这套系统功能点清晰,答辩时只需讲清楚核心业务流程即可。以下6个模块是重中之重,也是答辩评委最可能提问的地方。

1. 请假管理(核心业务流程 - 学生端)

  • 核心逻辑:学生提交请假申请→填写请假标题、类型、开始/结束日期、请假内容→系统自动计算请假天数→提交后状态为“待班主任审核”。
  • 代码要点
@Service
@Transactional
public void addQingjia(Qingjia qingjia) {
    // 1. 自动生成请假编号 QJ+年月日+流水号
    String uuid = "QJ" + LocalDate.now().toString().replace("-", "") 
                  + String.format("%04d", getTodayCount() + 1);
    qingjia.setQingjiaUuidNumber(uuid);
    
    // 2. 自动计算请假天数
    long days = ChronoUnit.DAYS.between(
        qingjia.getQingjiakaishiTime().toInstant(),
        qingjia.getQingjiajieshuTime().toInstant()
    );
    qingjia.setQingjiaNumber((int) days + 1);
    
    // 3. 设置初始审批状态为“待班主任审核”
    qingjia.setQingjiaYesnoTypes(1);
    qingjia.setInsertTime(new Date());
    qingjia.setCreateTime(new Date());
    qingjiaMapper.insert(qingjia);
    log.info("学生 {} 提交请假申请,编号:{}", qingjia.getYonghuId(), uuid);
}

2. 请假管理(核心业务流程 - 老师/班主任端)

  • 核心逻辑:班主任查看本班学生的请假申请→初审(通过/拒绝)→通过后状态变为“待系主任审核”→填写审核意见。
  • 代码要点(班主任初审)
@Service
@Transactional
public void teacherAudit(Integer qingjiaId, Integer status, String reply) {
    Qingjia qingjia = qingjiaMapper.selectByPrimaryKey(qingjiaId);
    if (qingjia.getQingjiaYesnoTypes() != 1) {
        throw new RuntimeException("该请假单状态异常,无法审核");
    }
    
    qingjia.setQingjiaYesnoText(reply);
    qingjia.setQingjiaShenheTime(new Date());
    
    if (status == 1) {  // 通过
        qingjia.setQingjiaYesnoTypes(2);  // 进入系主任审核
        log.info("班主任通过请假申请,进入系主任审核,请假编号:{}", qingjia.getQingjiaUuidNumber());
    } else {  // 拒绝
        qingjia.setQingjiaYesnoTypes(4);  // 已拒绝
        log.info("班主任拒绝请假申请,请假编号:{}", qingjia.getQingjiaUuidNumber());
    }
    qingjiaMapper.updateByPrimaryKey(qingjia);
}

3. 请假管理(核心业务流程 - 系主任端)

  • 核心逻辑:系主任查看通过班主任初审的请假申请→终审(通过/拒绝)→通过后自动更新考勤记录→填写最终审核意见。
  • 代码要点(系主任终审 + 考勤联动)
@Service
@Transactional
public void directorAudit(Integer qingjiaId, Integer status, String reply) {
    Qingjia qingjia = qingjiaMapper.selectByPrimaryKey(qingjiaId);
    if (qingjia.getQingjiaYesnoTypes() != 2) {
        throw new RuntimeException("该请假单状态异常,无法审核");
    }
    
    qingjia.setQingjiaYesnoText(reply);
    qingjia.setQingjiaShenheTime(new Date());
    
    if (status == 1) {  // 通过
        qingjia.setQingjiaYesnoTypes(3);  // 已通过
        // 关键:自动更新考勤记录
        updateKaoqinOnLeaveApproved(qingjia);
        log.info("系主任通过请假申请,请假编号:{}", qingjia.getQingjiaUuidNumber());
    } else {  // 拒绝
        qingjia.setQingjiaYesnoTypes(4);  // 已拒绝
        log.info("系主任拒绝请假申请,请假编号:{}", qingjia.getQingjiaUuidNumber());
    }
    qingjiaMapper.updateByPrimaryKey(qingjia);
}

// 请假通过后更新考勤
private void updateKaoqinOnLeaveApproved(Qingjia qingjia) {
    LocalDate start = qingjia.getQingjiakaishiTime().toLocalDate();
    LocalDate end = qingjia.getQingjiajieshuTime().toLocalDate();
    
    // 遍历请假日期范围内的每一天,插入考勤记录
    for (LocalDate date = start; !date.isAfter(end); date = date.plusDays(1)) {
        Kaoqin kaoqin = new Kaoqin();
        kaoqin.setYonghuId(qingjia.getYonghuId());
        kaoqin.setKaoqinTypes(5);  // 5=请假
        kaoqin.setKaoqinTime(date);
        kaoqin.setInsertTime(new Date());
        kaoqin.setCreateTime(new Date());
        kaoqinMapper.insert(kaoqin);
    }
}

4. 考勤管理(老师端)

  • 核心逻辑:老师可以录入/修改学生的日常考勤(正常/迟到/早退/旷课);期末统计学生出勤情况。
  • 页面设计:考勤列表按日期倒序排列;支持按班级、学生姓名、日期筛选。

5. 班级与课程管理(管理员端)

  • 核心逻辑:管理员管理班级信息(班级名称、位置、班主任);管理课程信息(课程名称、地点、任课老师、课程形式)。
  • 代码要点
public void addClazz(Clazz clazz) {
    // 校验班级名称是否重复
    ClazzExample example = new ClazzExample();
    example.createCriteria().andClazzNameEqualTo(clazz.getClazzName());
    List<Clazz> list = clazzMapper.selectByExample(example);
    if (!list.isEmpty()) {
        throw new RuntimeException("班级名称已存在");
    }
    clazz.setInsertTime(new Date());
    clazz.setCreateTime(new Date());
    clazzMapper.insert(clazz);
}

6. 公告管理(系主任/管理员端)

  • 核心逻辑:系主任和管理员发布通知公告(放假通知、补课安排等)→学生和老师可查看公告列表和详情。
  • 页面设计:公告列表按发布时间倒序排列;支持公告类型分类展示。 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

五、学生网上请假系统特色功能设计(关键加分项)

这套系统的核心在于“请假审批与考勤管理的完整闭环”,以下几个特色设计能让你的毕设脱颖而出:

1. 多级审批流程可视化

在学生和老师的请假管理界面,用标签清晰展示请假单的审批状态:

  • 待班主任审核:显示黄色标签,学生可撤回申请
  • 待系主任审核:显示蓝色标签,班主任审核已通过,等待系主任
  • 已通过:显示绿色标签,考勤已自动更新
  • 已拒绝:显示红色标签,显示拒绝原因

2. 请假与考勤联动统计

-- 统计学生出勤情况(正常/迟到/早退/旷课/请假)
SELECT 
    y.yonghu_name,
    COUNT(CASE WHEN k.kaoqin_types = 1 THEN 1 END) AS normal_days,
    COUNT(CASE WHEN k.kaoqin_types = 2 THEN 1 END) AS late_days,
    COUNT(CASE WHEN k.kaoqin_types = 3 THEN 1 END) AS early_days,
    COUNT(CASE WHEN k.kaoqin_types = 4 THEN 1 END) AS absent_days,
    COUNT(CASE WHEN k.kaoqin_types = 5 THEN 1 END) AS leave_days
FROM yonghu y
LEFT JOIN kaoqin k ON y.id = k.yonghu_id
WHERE y.clazz_id = #{clazzId}
GROUP BY y.id;

在系主任和老师后台展示班级出勤统计报表,按月/按学期统计,辅助学生管理决策。

3. 请假审批提醒(可选加分项)

  • 学生提交请假后,系统自动通知班主任(站内消息)
  • 班主任审批通过后,自动通知系主任
  • 最终审批通过/拒绝后,自动通知学生
  • 实现方式:数据库消息表 + 前端轮询或WebSocket

4. 请假类型统计分析

-- 统计各类请假类型的占比
SELECT 
    qingjia_types AS leave_type,
    COUNT(*) AS count,
    ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM qingjia), 2) AS percentage
FROM qingjia
WHERE qingjia_yesno_types = 3  -- 已通过的请假
GROUP BY qingjia_types
ORDER BY count DESC;

在管理员后台展示请假类型统计图表,为学校管理提供数据支持(如病假占比高可加强流感预防宣传)。

六、测试与答辩:流程演示为主,突出请假闭环

1. 核心测试用例

测试场景操作步骤预期结果
学生提交请假学生登录→新增请假→填写信息→提交请假单生成,状态为“待班主任审核”
班主任初审通过班主任登录→查看请假列表→审核通过请假单状态变为“待系主任审核”
系主任终审通过系主任登录→查看请假列表→审核通过请假单状态变为“已通过”,考勤表自动新增请假记录
学生查看进度学生登录→查看请假记录审批状态正确显示(待班主任/待系主任/已通过/已拒绝)
考勤统计老师登录→查看考勤统计学生出勤数据准确,包含请假天数

2. 答辩准备技巧

  • 演示流程分角色演示,强调闭环
    1. 管理员端:展示添加班级、添加学生、添加老师、添加系主任。
    2. 学生端:展示提交请假申请、查看审批进度。
    3. 班主任端:展示初审通过、查看班级学生列表。
    4. 系主任端:展示终审通过。
    5. 最终展示:在学生端查看请假单状态已变为“已通过”,并在考勤查看中看到对应日期已标记为请假,强调完整的请假-考勤联动闭环。
  • 业务讲解:准备一页PPT展示系统业务流程图,从“学生提交请假”到“考勤自动更新”的全过程。
  • 技术亮点
    • 多级审批流程设计:如何用状态字段实现待班主任审核→待系主任审核→已通过的流转。
    • 事务一致性:系主任终审通过时,同时更新请假单状态和插入考勤记录的事务管理。
    • 考勤自动更新算法:如何根据请假开始/结束日期自动生成多天考勤记录。
    • 统计报表:出勤统计、请假类型统计的实现。
  • 突出问题解决讲清楚“如何保证请假通过后考勤自动同步”(事务+考勤插入逻辑)“如何防止重复审批”(状态校验)“如何实现请假天数自动计算”(日期差计算)

结语

本文核心是“聚焦网上请假核心业务、实现多级审批与考勤联动、设计一套完整的请假管理系统”。毕设无需追求技术多炫酷,把学生(申请人)老师(初审人)系主任(终审人)、**考勤(结果关联)**之间的业务逻辑讲透,实现一个功能完整、流程闭环的系统,就足以成为答辩中的亮点。

若需完整项目源码(带详细注释)、测试数据SQL脚本、以及多级审批和考勤联动的完整代码,可在评论区留言“学生网上请假系统”获取;开发中遇问题(如审批状态流转、考勤自动更新、事务一致性),也可留言咨询~ 祝毕设顺利!🎉