【Java】实验室共享预约系统 SpringBoot+Vue框架 计算机毕业设计项目 Idea+Navicat+MySQL安装 附源码+文档+讲解

56 阅读6分钟

一、个人简介

💖💖作者:计算机编程果茶熊 💙💙个人简介:曾长期从事计算机专业培训教学,担任过编程老师,同时本人也热爱上课教学,擅长Java、微信小程序、Python、Golang、安卓Android等多个IT方向。会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。平常喜欢分享一些自己开发中遇到的问题的解决办法,也喜欢交流技术,大家有技术代码这一块的问题可以问我! 💛💛想说的话:感谢大家的关注与支持! 💜💜 网站实战项目 安卓/小程序实战项目 大数据实战项目 计算机毕业设计选题 💕💕文末获取源码联系计算机编程果茶熊

二、系统介绍

开发语言:Java+Python 数据库:MySQL 系统架构:B/S 后端框架:SpringBoot(Spring+SpringMVC+Mybatis)+Django 前端:Vue+HTML+CSS+JavaScript+jQuery

实验室共享预约系统是一个基于B/S架构的综合性实验室管理平台,采用Java语言开发,后端运用Spring Boot框架整合Spring、SpringMVC和Mybatis技术构建稳定的服务层,前端使用Vue框架实现动态交互界面,数据存储采用MySQL关系型数据库,开发环境基于IDEA工具完成。系统围绕高校实验室资源调度的实际需求,构建了涵盖人员管理、资源管理、预约管理、设备管理、教学管理五大模块的完整业务体系。功能模块包括学生与教师的账号信息维护、实验室类型分类与详细信息登记、教师和学生的在线预约申请与审批、用户反馈意见收集、实验设备的全流程管理(涵盖设备档案建立、借用登记、归还核验、维修记录追踪)、实验课程安排与管理、科研项目的创建立项与进度监控、学生实验报告的在线提交与教师评估打分、教学资源的分类存储与共享下载等核心业务。系统通过统一的Web界面为师生提供便捷的服务入口,管理员可通过后台实时掌握实验室使用状态和设备运行情况,实现了实验室资源从申请、使用到评价的全过程数字化管理,提升了资源配置效率和服务质量。

三、视频解说

实验室共享预约系统

四、部分功能展示

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

五、部分代码展示


// 核心功能1: 实验室预约管理 - 预约冲突检测与智能调度
@Service
public class ReservationService {
    
    @Autowired
    private ReservationMapper reservationMapper;
    
    @Autowired
    private LaboratoryMapper laboratoryMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Transactional(rollbackFor = Exception.class)
    public Result handleLabReservation(ReservationDTO reservationDTO) {
        Integer userId = reservationDTO.getUserId();
        Integer labId = reservationDTO.getLabId();
        Date startTime = reservationDTO.getStartTime();
        Date endTime = reservationDTO.getEndTime();
        Integer participantCount = reservationDTO.getParticipantCount();
        String purpose = reservationDTO.getPurpose();
        
        // 查询实验室信息验证容量
        Laboratory laboratory = laboratoryMapper.selectById(labId);
        if (laboratory == null) {
            return Result.error("实验室不存在");
        }
        if (participantCount > laboratory.getCapacity()) {
            return Result.error("预约人数超过实验室容量上限" + laboratory.getCapacity() + "人");
        }
        if (laboratory.getStatus().equals("maintenance")) {
            return Result.error("该实验室正在维护中,暂不可预约");
        }
        
        // 检测时间段冲突
        List<Reservation> conflictReservations = reservationMapper.selectConflictReservations(
            labId, startTime, endTime, Arrays.asList("pending", "approved")
        );
        if (!conflictReservations.isEmpty()) {
            StringBuilder conflictInfo = new StringBuilder("该时间段存在冲突预约: ");
            for (Reservation conflict : conflictReservations) {
                User conflictUser = userMapper.selectById(conflict.getUserId());
                conflictInfo.append(String.format("[%s %s-%s] ", 
                    conflictUser.getName(),
                    new SimpleDateFormat("MM-dd HH:mm").format(conflict.getStartTime()),
                    new SimpleDateFormat("HH:mm").format(conflict.getEndTime())
                ));
            }
            return Result.error(conflictInfo.toString());
        }
        
        // 验证用户预约权限和频率限制
        User currentUser = userMapper.selectById(userId);
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.DAY_OF_MONTH, -7);
        Date weekAgo = calendar.getTime();
        
        Integer weeklyReservationCount = reservationMapper.countUserReservations(
            userId, weekAgo, now
        );
        Integer maxWeeklyReservations = "teacher".equals(currentUser.getRole()) ? 10 : 3;
        if (weeklyReservationCount >= maxWeeklyReservations) {
            return Result.error("您本周预约次数已达上限" + maxWeeklyReservations + "次");
        }
        
        // 计算用户信用评分
        List<Reservation> userHistory = reservationMapper.selectUserReservationHistory(userId);
        double creditScore = calculateCreditScore(userHistory);
        
        // 计算预约优先级
        long daysUntilReservation = (startTime.getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
        double urgencyFactor = Math.max(0, 10 - daysUntilReservation) * 2;
        double priorityScore = creditScore * 0.7 + urgencyFactor * 0.3;
        
        // 根据优先级决定审批状态
        String status = priorityScore >= 70 ? "approved" : "pending";
        if ("teacher".equals(currentUser.getRole())) {
            status = "approved"; // 教师预约直接通过
        }
        
        // 创建预约记录
        Reservation reservation = new Reservation();
        reservation.setUserId(userId);
        reservation.setLabId(labId);
        reservation.setStartTime(startTime);
        reservation.setEndTime(endTime);
        reservation.setPurpose(purpose);
        reservation.setParticipantCount(participantCount);
        reservation.setPriorityScore(priorityScore);
        reservation.setStatus(status);
        reservation.setCreateTime(now);
        
        reservationMapper.insert(reservation);
        
        // 更新实验室使用统计
        laboratory.setTotalReservations(laboratory.getTotalReservations() + 1);
        laboratoryMapper.updateById(laboratory);
        
        Map<String, Object> resultData = new HashMap<>();
        resultData.put("reservationId", reservation.getId());
        resultData.put("status", status);
        resultData.put("priorityScore", priorityScore);
        resultData.put("message", "approved".equals(status) ? "预约成功" : "预约已提交,等待审批");
        
        return Result.success(resultData);
    }
    
    private double calculateCreditScore(List<Reservation> history) {
        if (history.isEmpty()) {
            return 80.0;
        }
        long totalCount = history.size();
        long completedCount = history.stream().filter(r -> "completed".equals(r.getStatus())).count();
        long cancelledCount = history.stream().filter(r -> "cancelled".equals(r.getStatus())).count();
        return (completedCount * 100.0 / totalCount) - (cancelledCount * 5.0);
    }
}


// 核心功能2: 设备借用归还管理 - 设备状态追踪与逾期处理
@Service
public class EquipmentBorrowService {
    
    @Autowired
    private EquipmentMapper equipmentMapper;
    
    @Autowired
    private EquipmentBorrowMapper borrowMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private MaintenanceRecordMapper maintenanceMapper;
    
    @Transactional(rollbackFor = Exception.class)
    public Result processEquipmentOperation(EquipmentOperationDTO dto) {
        String action = dto.getAction();
        Integer equipmentId = dto.getEquipmentId();
        Integer userId = dto.getUserId();
        
        Equipment equipment = equipmentMapper.selectById(equipmentId);
        if (equipment == null) {
            return Result.error("设备不存在");
        }
        
        if ("borrow".equals(action)) {
            return processBorrow(equipment, userId, dto);
        } else if ("return".equals(action)) {
            return processReturn(equipment, userId, dto);
        }
        return Result.error("无效的操作类型");
    }
    
    private Result processBorrow(Equipment equipment, Integer userId, EquipmentOperationDTO dto) {
        if (!"available".equals(equipment.getStatus())) {
            return Result.error("设备当前状态为" + equipment.getStatus() + ",无法借用");
        }
        
        Date expectedReturnDate = dto.getExpectedReturnDate();
        Date now = new Date();
        long borrowDays = (expectedReturnDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
        
        Integer maxBorrowDays = equipment.getMaxBorrowDays() != null ? equipment.getMaxBorrowDays() : 30;
        if (borrowDays > maxBorrowDays) {
            return Result.error("借用时长超过该设备最大限制" + maxBorrowDays + "天");
        }
        
        // 检查用户当前借用数量
        User user = userMapper.selectById(userId);
        Integer currentBorrowCount = borrowMapper.countUserCurrentBorrows(userId);
        Integer maxBorrowCount = "teacher".equals(user.getRole()) ? 5 : 2;
        
        if (currentBorrowCount >= maxBorrowCount) {
            return Result.error("您当前已借用" + currentBorrowCount + "件设备,达到上限");
        }
        
        // 检查用户是否有逾期未处理记录
        Integer overdueCount = borrowMapper.countUserOverdueRecords(userId);
        if (overdueCount > 0) {
            return Result.error("您有" + overdueCount + "条逾期归还记录未处理,暂不可借用");
        }
        
        // 创建借用记录
        EquipmentBorrow borrow = new EquipmentBorrow();
        borrow.setEquipmentId(equipmentId);
        borrow.setUserId(userId);
        borrow.setBorrowTime(now);
        borrow.setExpectedReturnTime(expectedReturnDate);
        borrow.setStatus("borrowed");
        borrowMapper.insert(borrow);
        
        // 更新设备状态
        equipment.setStatus("borrowed");
        equipment.setCurrentUserId(userId);
        equipment.setLastBorrowTime(now);
        equipmentMapper.updateById(equipment);
        
        Map<String, Object> result = new HashMap<>();
        result.put("borrowId", borrow.getId());
        result.put("expectedReturnDate", expectedReturnDate);
        return Result.success("借用成功", result);
    }
    
    private Result processReturn(Equipment equipment, Integer userId, EquipmentOperationDTO dto) {
        EquipmentBorrow borrow = borrowMapper.selectActiveBorrow(equipmentId, userId);
        if (borrow == null) {
            return Result.error("未找到对应的借用记录");
        }
        
        Date now = new Date();
        boolean isOverdue = now.after(borrow.getExpectedReturnTime());
        long overdueDays = 0;
        
        if (isOverdue) {
            overdueDays = (now.getTime() - borrow.getExpectedReturnTime().getTime()) / (1000 * 60 * 60 * 24);
        }
        
        String condition = dto.getCondition() != null ? dto.getCondition() : "normal";
        
        // 更新借用记录
        borrow.setActualReturnTime(now);
        borrow.setIsOverdue(isOverdue ? 1 : 0);
        borrow.setOverdueDays((int)overdueDays);
        borrow.setReturnCondition(condition);
        borrow.setStatus("returned");
        borrowMapper.updateById(borrow);
        
        // 分析用户历史逾期情况
        List<EquipmentBorrow> userHistory = borrowMapper.selectUserBorrowHistory(userId);
        if (!userHistory.isEmpty()) {
            long overdueRecords = userHistory.stream().filter(b -> b.getIsOverdue() == 1).count();
            double overdueRate = (overdueRecords * 100.0) / userHistory.size();
            
            if (overdueRate > 30) {
                // 创建用户警告记录(此处简化处理)
                User user = userMapper.selectById(userId);
                user.setWarningCount(user.getWarningCount() + 1);
                userMapper.updateById(user);
            }
        }
        
        // 根据设备状态更新
        if ("damaged".equals(condition) || "malfunction".equals(condition)) {
            equipment.setStatus("maintenance");
            
            // 创建维修记录
            MaintenanceRecord maintenance = new MaintenanceRecord();
            maintenance.setEquipmentId(equipmentId);
            maintenance.setReportedBy(userId);
            maintenance.setIssueDescription(dto.getIssueDescription());
            maintenance.setStatus("pending");
            maintenance.setReportTime(now);
            maintenanceMapper.insert(maintenance);
        } else {
            equipment.setStatus("available");
        }
        
        equipment.setCurrentUserId(null);
        equipment.setTotalBorrowCount(equipment.getTotalBorrowCount() + 1);
        equipmentMapper.updateById(equipment);
        
        Map<String, Object> result = new HashMap<>();
        result.put("isOverdue", isOverdue);
        result.put("overdueDays", overdueDays);
        result.put("equipmentStatus", equipment.getStatus());
        String message = isOverdue ? "归还成功,逾期" + overdueDays + "天" : "归还成功";
        return Result.success(message, result);
    }
}


// 核心功能3: 实验报告评估与统计分析
@Service
public class ReportEvaluationService {
    
    @Autowired
    private ExperimentReportMapper reportMapper;
    
    @Autowired
    private ReportEvaluationMapper evaluationMapper;
    
    @Autowired
    private CourseMapper courseMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Transactional(rollbackFor = Exception.class)
    public Result analyzeAndEvaluateReports(EvaluationRequestDTO request) {
        Integer courseId = request.getCourseId();
        Integer teacherId = request.getTeacherId();
        
        // 获取待评估报告
        List<ExperimentReport> pendingReports = reportMapper.selectByCourseAndStatus(courseId, "submitted");
        if (pendingReports.isEmpty()) {
            return Result.error("暂无待评估报告");
        }
        
        Course course = courseMapper.selectById(courseId);
        Date deadline = course.getReportDeadline();
        
        List<Map<String, Object>> evaluationResults = new ArrayList<>();
        List<Double> allScores = new ArrayList<>();
        
        for (ExperimentReport report : pendingReports) {
            // 计算提交延迟天数
            long delayDays = 0;
            if (report.getSubmitTime().after(deadline)) {
                delayDays = (report.getSubmitTime().getTime() - deadline.getTime()) / (1000 * 60 * 60 * 24);
            }
            
            // 字数评分(满分20分)
            double wordScore = Math.min(20, report.getWordCount() / 100.0);
            
            // 附件完整性评分(满分15分)
            double attachmentScore = Math.min(15, report.getAttachmentCount() * 5);
            
            // 提交及时性评分(满分10分)
            double timelinessScore = delayDays > 0 ? Math.max(0, 10 - delayDays * 2) : 10;
            
            // 查询学生历史报告表现
            List<ReportEvaluation> studentHistory = evaluationMapper.selectStudentHistory(report.getStudentId());
            double historyBonus = 0;
            if (!studentHistory.isEmpty()) {
                double avgHistoryScore = studentHistory.stream()
                    .mapToDouble(ReportEvaluation::getTotalScore)
                    .average()
                    .orElse(0);
                if (avgHistoryScore >= 85) {
                    historyBonus = 5;
                } else if (avgHistoryScore >= 75) {
                    historyBonus = 3;
                }
            }
            
            // 内容质量基础分(满分50,默认给中等水平)
            double contentBaseScore = 35;
            
            // 计算初步总分
            double preliminaryScore = wordScore + attachmentScore + timelinessScore + historyBonus + contentBaseScore;
            
            // 创建评估记录
            ReportEvaluation evaluation = new ReportEvaluation();
            evaluation.setReportId(report.getId());
            evaluation.setEvaluatorId(teacherId);
            evaluation.setWordScore(wordScore);
            evaluation.setAttachmentScore(attachmentScore);
            evaluation.setTimelinessScore(timelinessScore);
            evaluation.setContentScore(contentBaseScore);
            evaluation.setTotalScore(preliminaryScore);
            evaluation.setStatus("preliminary");
            evaluation.setEvaluationTime(new Date());
            evaluationMapper.insert(evaluation);
            
            // 更新报告状态
            report.setStatus("evaluated");
            reportMapper.updateById(report);
            
            allScores.add(preliminaryScore);
            
            Map<String, Object> resultItem = new HashMap<>();
            resultItem.put("reportId", report.getId());
            resultItem.put("studentId", report.getStudentId());
            resultItem.put("preliminaryScore", preliminaryScore);
            resultItem.put("delayDays", delayDays);
            evaluationResults.add(resultItem);
        }
        
        // 统计分析
        double avgScore = allScores.stream().mapToDouble(Double::doubleValue).average().orElse(0);
        double maxScore = allScores.stream().mapToDouble(Double::doubleValue).max().orElse(0);
        double minScore = allScores.stream().mapToDouble(Double::doubleValue).min().orElse(0);
        
        // 计算标准差
        double variance = allScores.stream()
            .mapToDouble(score -> Math.pow(score - avgScore, 2))
            .average()
            .orElse(0);
        double stdDev = Math.sqrt(variance);
        
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("totalReports", evaluationResults.size());
        statistics.put("averageScore", Math.round(avgScore * 100) / 100.0);
        statistics.put("maxScore", maxScore);
        statistics.put("minScore", minScore);
        statistics.put("standardDeviation", Math.round(stdDev * 100) / 100.0);
        
        Map<String, Object> finalResult = new HashMap<>();
        finalResult.put("evaluatedCount", evaluationResults.size());
        finalResult.put("statistics", statistics);
        finalResult.put("details", evaluationResults);
        
        return Result.success("批量评估完成", finalResult);
    }
}



六、部分文档展示

在这里插入图片描述

七、END

💕💕文末获取源码联系计算机编程果茶熊