基于Vue与SpringBoot的学生请假系统:从架构设计到部署上线的全栈实践
简介这是一套面向计算机专业本科生的毕业设计/课程设计级学生请假系统实战项目采用VueSpringBoot前后端分离架构解决高校教学管理中请假流程不规范、信息同步滞后、三方协作低效等实际问题。资源包共401个文件含97个Java后端核心代码文件Controller/Service/DAO层、40个Vue组件文件含请假、审核、管理等业务界面、32张JPG/PNG系统截图与UI素材、16个JS工具脚本、12个XML配置及1个T108.sql数据库建表脚本完整覆盖从环境搭建、接口开发、页面交互到数据持久化的全流程压缩包仅9.52MB轻量易部署。已有23人学习下载配套提供开题报告、功能文档、README部署指南及清晰的back/front双目录结构便于快速理解模块划分与调用关系特别适合作为期末大作业参考或SpringBootVue全栈开发入门实践范例。1. 项目概述一个现代学生请假系统的诞生最近在整理过往项目时翻到了一个挺有意思的“老伙计”——一个基于Vue和SpringBoot开发的学生请假系统。说它老其实技术栈现在看依然主流但当时为了把它从零到一搭起来确实踩了不少坑也积累了不少心得。这个系统本质上是一个典型的校园管理场景下的业务流程数字化工具核心目标就是把学生、辅导员、院系领导之间那套繁琐的纸质请假流程搬到线上实现无纸化、流程化和可追溯化。想象一下学生不用再拿着请假条到处找老师签字老师也不用担心假条丢失或信息混乱所有流程在线上清晰可见状态实时更新这就是它要解决的核心痛点。这个项目非常适合正在学习前后端分离开发的朋友尤其是对Vue和SpringBoot有初步了解想找一个有完整业务逻辑的实战项目来练手的人。通过它你不仅能巩固Vue组件化开发、路由管理、状态管理Vuex/Pinia以及SpringBoot的Web开发、数据库操作MyBatis/MyBatis-Plus/JPA、权限控制Spring Security或Sa-Token等核心技术更能深入理解一个业务系统从需求分析、数据库设计、接口定义到前后端联调、部署上线的完整生命周期。你会发现技术栈只是工具如何用这些工具高效、优雅地解决真实的业务问题才是更有挑战也更有价值的部分。接下来我就把这个项目的设计思路、关键实现细节以及那些“踩坑”后总结的经验毫无保留地分享出来。2. 系统整体架构与核心设计思路2.1 为什么选择Vue SpringBoot在技术选型上我们几乎没怎么犹豫就定下了Vue SpringBoot这套组合拳。原因很直接它们分别代表了当前前端和后端领域最成熟、最流行、社区最活跃的技术方案之一能极大提升开发效率和项目的可维护性。前端选择Vue的考量学生请假系统的前端界面交互逻辑清晰但表单多、状态管理需求明确如用户登录状态、请假单列表状态。Vue的响应式数据绑定和组件化开发模式非常适合构建这类以表单和列表操作为主的后台管理系统。通过Vue CLI可以快速搭建项目骨架配合Element Plus或Ant Design Vue这类成熟的UI组件库能让我们把精力聚焦在业务逻辑而非样式细节上。Vue Router处理页面跳转Vuex或Pinia管理全局状态如用户信息、权限令牌整个前端架构清晰、易于上手和维护。后端选择SpringBoot的考量后端需要处理复杂的业务逻辑、数据持久化、权限校验和API提供。SpringBoot的“约定大于配置”理念和强大的自动配置能力让我们能快速搭建一个稳健的后端服务。它内嵌了Tomcat等Web服务器简化了部署通过Spring Data JPA或MyBatis-Plus可以极简地操作数据库Spring Security或更轻量的Sa-Token能优雅地解决认证与授权问题。此外SpringBoot生态丰富整合Redis缓存、RabbitMQ异步通知、SwaggerAPI文档等中间件都非常方便为系统未来的扩展预留了空间。前后端分离的优势采用前后端分离架构前端负责页面渲染和用户交互后端通过RESTful API提供数据服务。这种模式让前后端开发可以并行进行通过接口文档如Swagger定义好契约即可各自推进。部署也更为灵活前端可以部署在Nginx或对象存储上后端独立部署通过CORS解决跨域问题。这比传统的JSP、Thymeleaf等模板引擎渲染方式更符合现代Web开发趋势。2.2 核心业务流程与角色权限设计任何管理系统理清业务流程和角色权限是设计的基石。学生请假系统通常涉及三类核心角色学生、辅导员或班主任、院系领导或学工处老师。核心业务流程学生发起请假学生登录系统填写请假表单包括请假类型、时间、事由、附件等提交申请。辅导员审批辅导员在自己的待办列表中看到学生的请假申请可以查看详情并选择“批准”或“驳回”。如果驳回需填写驳回理由。院系领导审批可选根据请假时长或类型系统可能设定规则例如请假超过3天需要院系领导二次审批。此时申请会流转到相应领导处。销假与归档学生返校后可能需要进行销假操作。所有已完成的请假记录归档可供查询和统计。角色权限设计RBAC模型我们采用基于角色的访问控制RBAC模型这是管理后台系统的黄金标准。学生权限最小只能操作与自己相关的数据。包括发起请假、查看自己的请假记录历史、销假、修改个人信息。辅导员拥有管辖班级或年级学生的数据权限。包括审批/驳回所辖学生的请假申请、查看所辖学生的请假记录、导出报表。院系领导/管理员拥有更广的数据权限和系统管理权限。包括审批需要上级审批的请假单、查看全院系的请假统计与分析、管理学生和辅导员的基础信息、管理系统字典如请假类型。超级管理员拥有所有权限通常负责角色管理、用户管理、系统配置等。注意权限设计一定要与业务部门反复确认。“辅导员能否修改已提交的假条”、“领导能否查看所有学院的统计”这类边界问题必须在设计初期明确否则后期改动成本巨大。我们当时就曾因为“辅导员能否代学生提交请假”这个需求变更而返工了部分接口和界面逻辑。2.3 数据库表结构关键设计数据库设计是系统的“骨架”设计得好后续开发事半功倍。这里列出几个核心表及其关键字段的设计思路用户表 (sys_user)id(主键),username(学号/工号),password(加密存储),real_name,role_id(关联角色),class_id(关联班级学生特有),phone,email,status(账号状态)。设计要点密码必须使用BCrypt等强哈希算法加密绝对禁止明文存储。role_id用于RBAC权限控制。角色表 (sys_role)与权限表 (sys_menu)定义角色如student, teacher, admin和前端菜单/按钮权限。通过关联表sys_role_menu建立角色与权限的多对多关系。请假申请表 (leave_application)id(主键),student_id(申请人),type(请假类型),start_time,end_time,duration(时长可计算得出),reason(事由),attachment_url(附件链接),status(审批状态待审核、辅导员通过、领导通过、已驳回、已销假),current_approver_id(当前审批人),reject_reason(驳回理由),create_time,update_time。设计要点status字段是流程驱动的核心所有业务逻辑都围绕它展开。current_approver_id可用于快速定位待办任务。duration字段建议在提交时由后端计算并存储避免每次查询时计算。审批流程表 (leave_approval_flow)这是一个可选的、用于支持更复杂固定流程的表。如果审批流程固定如学生-辅导员-领导可以设计此表记录每个审批环节。id,application_id,approver_role,approver_id,approval_status,approval_time,comments。设计要点对于简单的两级审批可以通过在leave_application表中增加teacher_approval_status和leader_approval_status字段来简化。但使用独立的流程表更灵活易于扩展多级审批或会签。通知表 (sys_notification)用于存储系统内的消息通知如“你有新的待审批请假单”、“你的请假申请已被批准”。id,user_id,title,content,type,related_id(关联业务ID如请假单ID),is_read,create_time。设计要点这是提升用户体验的关键。可以通过WebSocket实现实时推送或由前端定时轮询此表。3. 前端Vue核心实现细节3.1 项目初始化与基础架构搭建使用Vue CLI或Vite可以快速初始化项目。我更喜欢Vite因为它启动和热更新速度更快。创建项目后需要规划好目录结构一个清晰的目录是项目可维护性的保障。src/ ├── api/ # 所有后端接口请求封装按模块划分 ├── assets/ # 静态资源 ├── components/ # 公共组件如PageHeader, UploadFile ├── layout/ # 布局组件包含Header, Sidebar, Footer ├── router/ # Vue Router配置 ├── store/ # 状态管理Vuex modules 或 Pinia stores ├── utils/ # 工具函数请求封装、日期处理、权限校验 ├── views/ # 页面视图组件如Login, LeaveList, ApprovalList └── App.vue main.js关键步骤封装axios在utils/request.js中封装axios实例统一设置baseURL、超时时间、请求/响应拦截器。在请求拦截器中为每个请求自动添加Authorization头携带Token在响应拦截器中统一处理错误如401跳转登录页403提示权限不足。配置Vue Router实现路由懒加载提升性能。在路由守卫beforeEach中进行权限校验检查用户Token和路由元信息meta中的角色要求决定是否允许跳转。集成状态管理使用Pinia更推荐或Vuex。创建一个userStore来管理登录用户信息、Token和权限列表。用户登录成功后将用户信息和Token存入store并持久化到localStorage或Cookie。引入UI组件库安装Element Plus或Ant Design Vue并全局注册。根据设计稿进行主题定制。3.2 核心页面组件开发与状态管理登录页 (Login.vue)除了表单验证关键是在登录成功后调用userStore的登录action保存Token并获取用户详细信息及权限菜单列表然后动态生成路由如果采用后端返回路由表的方式最后跳转到主页。主页布局 (Layout.vue)通常包含顶部导航、侧边栏菜单、内容区域router-view。侧边栏菜单应根据userStore中存储的权限菜单列表动态渲染。这里会遇到一个经典问题页面刷新后Vuex/Pinia状态丢失。解决方案是在main.js或App.vue的创建阶段先从localStorage读取Token然后调用接口重新获取用户信息并更新store。请假申请页 (LeaveApply.vue)表单处理使用UI库的Form组件配置好规则校验如请假时间不能早于当前时间结束时间需晚于开始时间。对于请假类型等选项应从后端接口动态获取字典数据而不是写死在前端。附件上传使用el-upload组件配置action指向后端上传接口限制文件大小和类型。上传成功后将服务器返回的文件路径或URL绑定到表单模型的attachment_url字段。提交逻辑提交前进行最终验证通过后调用api/leave.js中封装的提交接口。提交成功后给出友好提示并可能跳转到请假记录页。我的请假记录页 (MyLeaveList.vue)列表展示使用Table组件列包括请假单号、类型、时间、时长、状态、操作等。状态筛选与搜索提供状态下拉筛选和日期范围搜索。将筛选条件作为参数传递给后端接口。分页集成分页组件与后端分页查询接口对接。操作列根据状态动态显示操作按钮。如“待审批”状态可显示“撤销”按钮“已批准”状态可显示“销假”按钮。点击“查看”可跳转到详情页或打开抽屉组件展示详情。审批管理页 (ApprovalList.vue)这是辅导员和领导的页面。核心是获取status为“待审核”且current_approver_id为自己的请假列表。批量操作可以支持批量审批通过或驳回。审批抽屉/对话框点击“审批”打开一个抽屉展示请假详情并有一个表单供审批人输入审批意见尤其是驳回时。3.3 前端性能与体验优化实践路由懒加载在router/index.js中使用() import(/views/...)语法实现路由组件懒加载减少首屏加载体积。API请求防抖与缓存对于搜索框输入使用防抖函数如lodash的_.debounce减少不必要的请求。对于字典数据等不常变化的数据可以在首次获取后存入store或localStorage进行缓存。大文件上传优化如果支持上传视频等大文件可以考虑分片上传和断点续传。前端使用File.slice方法切割文件并记录上传进度。实时通知为了提升审批流程的即时性可以集成WebSocket。当学生提交请假或领导完成审批时后端通过WebSocket主动推送消息给相关用户的前端前端收到后更新store中的通知数量并弹出提示。如果项目规模不大使用定时轮询查询sys_notification表也是简单可行的方案。实操心得在开发过程中一定要养成“先定义接口再实现前端”的习惯。和后端同学一起维护一份详细的Swagger或YApi文档能极大减少联调时的摩擦。另外前端对于日期时间字段要特别小心建议统一使用dayjs库处理并在与后端交互时明确时区通常使用UTC时间或时间戳。4. 后端SpringBoot核心实现细节4.1 项目结构与分层设计遵循经典的分层架构职责清晰便于维护和测试。com.example.leave ├── LeaveApplication.java # 启动类 ├── config/ # 配置类Web, Security, Redis等 ├── controller/ # 控制层接收请求返回响应 ├── service/ # 业务逻辑层接口与实现分离 │ ├── impl/ ├── mapper/ 或 repository/ # 数据访问层MyBatis Mapper 或 JPA Repository ├── entity/ 或 domain/ # 实体类与数据库表对应 ├── dto/ # 数据传输对象请求/响应封装 ├── vo/ # 视图对象用于前端展示的复杂对象 ├── common/ # 通用模块常量、工具类、异常、统一返回结果 └── interceptor/ 或 filter/ # 拦截器或过滤器用于日志、权限等统一返回结果在common包下定义一个ResultT类包含code、msg、data字段。所有Controller方法都返回Result对象方便前端统一处理。全局异常处理使用ControllerAdvice和ExceptionHandler创建一个全局异常处理器。将业务异常如ServiceException、参数校验异常MethodArgumentNotValidException、权限异常等捕获并转换为友好的Result对象返回给前端。4.2 用户认证与权限拦截实现这是后台系统的安全核心。我们选择用Spring Security JWT的方案轻量且无状态。集成Spring Security引入spring-boot-starter-security依赖。编写一个SecurityConfig配置类继承WebSecurityConfigurerAdapterSpring Security 5.x或使用组件式配置Spring Security 6。自定义UserDetailsService实现loadUserByUsername方法根据用户名学号/工号从数据库查询用户信息及权限列表封装成UserDetails对象返回。JWT工具类编写JwtUtil用于生成Token、解析Token、校验Token有效性。Token中通常包含用户名、用户ID和权限信息。认证过滤器 (JwtAuthenticationFilter)创建一个过滤器在UsernamePasswordAuthenticationFilter之前执行。从请求头Authorization中提取JWT Token解析并验证。如果有效则根据Token中的信息构造一个Authentication对象并存入SecurityContextHolder表示用户已认证。权限注解控制在SecurityConfig中启用方法级安全注解EnableGlobalMethodSecurity(prePostEnabled true)。然后在Service方法或Controller方法上使用PreAuthorize(“hasAuthority(‘leave:approve’)”)或PreAuthorize(“hasRole(‘TEACHER’)”)进行细粒度权限控制。放行公开接口在SecurityConfig中通过http.authorizeRequests().antMatchers(“/api/auth/login”, “/swagger-ui/**”).permitAll()配置不需要认证的接口如登录、Swagger文档。踩坑记录最初我们直接将用户所有权限列表放在JWT Token中导致Token过长。后来改为Token中只存用户ID和关键信息用户登录时将其权限列表存入RedisKey为user:perms:${userId}在每次鉴权时从Redis获取。这样既安全又高效。另外别忘了设置Token的过期时间和续签逻辑。4.3 请假业务核心逻辑与事务管理请假审批是一个典型的业务流程涉及多张表的操作必须保证事务的一致性。LeaveApplicationService核心方法伪代码Service Transactional // 类级别声明事务 public class LeaveApplicationServiceImpl implements LeaveApplicationService { Autowired private LeaveApplicationMapper leaveAppMapper; Autowired private NotificationService notificationService; Autowired private SysUserMapper userMapper; Override public Result submitApplication(LeaveApplicationDTO dto, Long currentUserId) { // 1. 数据校验时间逻辑、附件大小等 // 2. 构造实体对象设置状态为“待审核”当前审批人为辅导员ID LeaveApplication entity convertToEntity(dto); entity.setStatus(PENDING); // 假设通过学生ID找到其辅导员ID Long teacherId findTeacherIdByStudentId(currentUserId); entity.setCurrentApproverId(teacherId); // 3. 保存请假申请 leaveAppMapper.insert(entity); // 4. 发送系统通知给辅导员异步 notificationService.sendNotification(teacherId, “新的请假待审批”, entity.getId()); // 5. 记录日志可选 return Result.success(“提交成功”, entity.getId()); } Override public Result approveApplication(Long applicationId, ApprovalDTO approvalDTO, Long approverId) { // 1. 查询请假申请并校验状态和审批人权限 LeaveApplication app leaveAppMapper.selectById(applicationId); if (app null || !PENDING.equals(app.getStatus()) || !approverId.equals(app.getCurrentApproverId())) { throw new ServiceException(“审批状态异常或无权操作”); } // 2. 更新申请状态 if (APPROVED.equals(approvalDTO.getAction())) { // 判断是否需要下一级审批根据请假时长等规则 if (needNextLevelApproval(app)) { app.setStatus(TEACHER_APPROVED); // 辅导员通过待领导审批 app.setCurrentApproverId(findLeaderId(app)); // 找到领导ID // 发送通知给领导 notificationService.sendNotification(app.getCurrentApproverId(), ...); } else { app.setStatus(FINAL_APPROVED); // 最终通过 app.setCurrentApproverId(null); // 发送通知给学生 notificationService.sendNotification(app.getStudentId(), ...); } } else if (REJECTED.equals(approvalDTO.getAction())) { app.setStatus(REJECTED); app.setRejectReason(approvalDTO.getComments()); app.setCurrentApproverId(null); // 发送驳回通知给学生 notificationService.sendNotification(app.getStudentId(), ...); } // 3. 更新数据库 leaveAppMapper.updateById(app); // 4. 记录审批流水如果需要 // saveApprovalFlow(app, approverId, approvalDTO); return Result.success(“操作成功”); } }事务管理要点在Service方法上使用Transactional注解确保方法内的所有数据库操作要么全部成功要么全部回滚。特别是在“审批”方法中更新申请状态和发送通知如果通知是同步保存到数据库必须在同一个事务内。4.4 数据持久化与MyBatis-Plus高效使用我们选用MyBatis-PlusMP作为ORM框架它是对MyBatis的增强提供了强大的CRUD封装和条件构造器。实体类与Mapper使用TableName注解实体类使用TableId注解主键。Mapper接口只需继承BaseMapperEntity即可获得大部分单表操作方法。Service层封装Service接口继承IServiceEntityServiceImpl继承ServiceImplMapper, Entity并实现自己的接口可以快速获得批量操作、链式查询等能力。条件查询在查询请假列表时会涉及多条件动态查询。MP提供了QueryWrapper或LambdaQueryWrapper可以优雅地构建动态查询条件。LambdaQueryWrapperLeaveApplication wrapper new LambdaQueryWrapper(); wrapper.eq(LeaveApplication::getStudentId, studentId); // 学生只能看自己的 wrapper.eq(status ! null, LeaveApplication::getStatus, status); // 动态状态筛选 wrapper.ge(startTime ! null, LeaveApplication::getStartTime, startTime); // 开始时间之后 wrapper.le(endTime ! null, LeaveApplication::getEndTime, endTime); // 结束时间之前 wrapper.orderByDesc(LeaveApplication::getCreateTime); // 按创建时间倒序 PageLeaveApplication page new Page(current, size); return leaveAppMapper.selectPage(page, wrapper);分页插件需要配置分页插件PaginationInterceptorMP 3.x或MybatisPlusInterceptorMP 3.4才能让selectPage方法生效。逻辑删除对于用户表等数据通常采用逻辑删除而非物理删除。在实体类字段上使用TableLogic注解MP会在执行删除操作时自动更新该字段为删除状态查询时自动过滤已删除数据。5. 前后端联调与部署上线5.1 接口联调与跨域问题解决前后端分离开发联调是必经环节。Swagger或Knife4j是后端开发者的福音它能自动生成API文档并提供测试界面。集成Swagger引入springfox-boot-starter或knife4j-spring-boot-starter依赖简单配置即可。在Controller方法上使用ApiOperation等注解补充说明。定义清晰的DTO前后端交互的数据对象要定义清晰。请求参数使用Validated注解配合校验注解如NotBlank,Future进行校验。返回结果使用统一的Result包装。解决跨域CORS在开发环境前端运行在localhost:8080后端在localhost:8081浏览器会因同源策略阻止请求。在后端配置一个全局的CORS过滤器即可解决。Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(“/api/**”) // 拦截路径 .allowedOriginPatterns(“*”) // 生产环境应指定具体前端地址 .allowedMethods(“GET”, “POST”, “PUT”, “DELETE”, “OPTIONS”) .allowCredentials(true) .maxAge(3600); } }联调工具使用Postman或Apifox进行接口测试确保每个接口的请求参数、响应格式、错误码都符合约定。5.2 系统部署与运维考量项目开发完成后部署上线是临门一脚。后端部署打包使用mvn clean package -DskipTests打包生成可执行的jar文件。环境配置使用application-{profile}.properties或application-{profile}.yml管理不同环境dev, test, prod的配置如数据库连接、Redis地址。通过启动参数--spring.profiles.activeprod激活生产环境配置。运行在服务器上使用nohup java -jar your-app.jar 后台运行。更推荐使用Docker容器化部署编写Dockerfile构建镜像后运行便于管理和迁移。反向代理通常不会直接暴露SpringBoot的8080端口。使用Nginx作为反向代理将域名请求转发到后端服务同时Nginx还可以处理静态文件、负载均衡和SSL证书HTTPS。前端部署构建运行npm run build或yarn build生成静态文件在dist目录。托管将dist目录下的文件上传到Web服务器如Nginx、Apache或对象存储如阿里云OSS、腾讯云COS并配置CDN加速。在Nginx中需要配置try_files指令来处理Vue Router的history模式下的路由回退问题。location / { root /path/to/your/dist; index index.html index.htm; try_files $uri $uri/ /index.html; # 关键配置 }API代理在前端部署的同一个域名下为了避免跨域可以在Nginx中配置将/api路径的请求代理到后端服务。location /api/ { proxy_pass http://backend-server:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }运维监控日志使用Logback或Log4j2合理配置日志级别和滚动策略。生产环境将日志收集到ELK或Graylog等集中日志系统。健康检查Spring Boot Actuator提供了/health,/metrics等端点可用于监控应用状态。数据库备份定期备份数据库是必须的。6. 开发中遇到的典型问题与解决方案在实际开发中总会遇到一些预料之外的问题。这里记录几个有代表性的问题一前端页面刷新后侧边栏菜单消失或跳转到登录页。现象用户登录后一切正常但一刷新页面Vuex中存储的用户信息和菜单就丢失了路由守卫发现无Token或用户信息就被重定向到登录页。根因Vuex/Pinia的状态存储在内存中页面刷新会重新初始化JavaScript环境导致状态丢失。解决方案持久化存储用户登录成功后不仅将Token和用户信息存入Vuex也同步存入localStorage或sessionStorage。应用初始化时恢复状态在App.vue的created或mounted钩子或路由守卫的全局前置钩子中判断localStorage中是否有Token。如果有则调用后端“获取当前用户信息”的接口用返回的数据重新填充Vuex。这样用户就感觉不到刷新带来的状态丢失。注意安全敏感信息不建议长期存放在localStorage中可以考虑sessionStorage标签页关闭即清除或加密存储。问题二审批通知的实时性要求。需求学生提交请假后辅导员能立刻感知而不是等下次刷新页面。方案选型短轮询前端定时如每30秒调用“获取未读通知数”接口。实现简单但实时性差且无效请求多。长轮询稍复杂实时性较好。WebSocket双向通信实时性最好但需要后端支持WebSocket并维护连接状态复杂度最高。我们的选择由于项目初期对实时性要求不是极端高我们采用了“短轮询 重要操作主动提示”的折中方案。即常规轮询间隔设为60秒但在学生提交请假或老师审批完成后后端除了存数据库还会调用一个内部方法如果目标用户当前在线可以通过一个简单的在线状态表维护或利用WebSocket连接池判断则尝试通过已建立的WebSocket连接如果存在立即推送一条通知。这样平衡了开发复杂度和用户体验。问题三请假时长计算的边界情况。场景计算请假时长单位天。学生请假从“2023-10-01 08:00”到“2023-10-03 18:00”。** naive计算**(结束时间戳 - 开始时间戳) / (24 * 3600 * 1000)得到约2.4天。业务需求通常请假是按“天”为单位审批可能需要四舍五入或者有特殊规则如不足半天按半天算超过半天按一天算。解决方案在后端submitApplication方法中根据业务规则编写专用的时长计算工具方法而不是简单的时间差。例如public static double calculateDurationDays(Date start, Date end) { long diffMs end.getTime() - start.getTime(); double diffDays (double) diffMs / (1000 * 3600 * 24); // 业务规则4小时为0.5天超过4小时不足8小时算0.5天超过8小时算1天 // 更复杂的规则可能涉及节假日排除... return Math.ceil(diffDays * 2) / 2.0; // 向上取整到0.5的倍数 }这个计算逻辑必须与业务部门确认并在接口文档中明确说明。问题四数据库查询性能随着数据量增大而变慢。现象当请假记录达到几万条时辅导员查询待审批列表或历史列表时响应变慢。分析检查发现查询语句没有有效利用索引或者进行了全表扫描。优化措施添加索引在leave_application表的status、current_approver_id、student_id、create_time等经常用于查询和排序的字段上创建索引。避免SELECT *在Mapper XML或MP的Wrapper中明确指定需要查询的字段。分页查询务必使用分页避免一次性拉取大量数据。MP的分页插件会自动在查询语句后加上LIMIT。关联查询优化查询请假列表时经常需要连表查询学生姓名、班级等信息。可以使用MyBatis的association进行一对一映射但要注意N1查询问题。对于性能要求高的场景可以考虑在业务层做两次查询或者使用TableField(exist false)注解配合自定义查询方法来手动填充VO对象。7. 项目扩展与进阶思考一个基础的学生请假系统上线后还可以从多个维度进行扩展使其更强大、更智能。流程引擎集成如果审批流程变得非常复杂多级、条件分支、会签、或签可以考虑集成工作流引擎如Activiti、Flowable或Camunda。将请假流程的定义和运行交给引擎管理系统只负责提供业务表单和与引擎交互流程的变更无需修改代码。移动端支持开发微信小程序或uni-app跨端应用让学生和老师能随时随地处理请假事务。后端API需要做适当适配如支持JSON Web Token的无状态认证。数据统计与分析利用ECharts等图表库在管理后台增加数据看板。展示按时间、按班级、按请假类型的统计图表帮助管理者洞察趋势。接入第三方认证允许学生和老师使用学校统一身份认证系统如CAS、OAuth2登录避免维护另一套账号密码。微服务化改造如果系统规模扩大可以考虑拆分为用户服务、请假服务、审批流程服务、通知服务等独立的微服务通过Spring Cloud AlibabaNacos, Sentinel, Gateway进行治理提高系统的弹性和可扩展性。容器化与CI/CD使用Docker Compose或Kubernetes编排所有服务前端、后端、数据库、Redis等。结合GitLab CI/CD或Jenkins实现代码提交后自动构建、测试、部署提升交付效率。这个基于Vue和SpringBoot的学生请假系统虽然业务场景不复杂但它几乎涵盖了现代Web应用开发的全部核心要素前后端分离、RESTful API、数据库设计、用户认证、权限控制、事务管理、文件上传、实时通信、性能优化、部署运维。把它吃透你就拥有了独立开发一个完整后台管理系统的基本能力。希望我的这些分享能帮你绕过一些我曾经跌入的坑更顺畅地完成你的项目。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →