package com.ruoyi.web.controller.service; import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.ruoyi.system.domain.SysVisitorRecord; import com.ruoyi.system.mapper.SysVisitorRecordMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; /** * 访客记录定时任务服务 * * @author ruoyi */ @Slf4j @Service public class VisitorRecordScheduleService { @Autowired private SysVisitorRecordMapper visitorRecordMapper; /** * 每天23:59:59执行,处理超期未签离的记录 * 将当天到期且未签离的记录状态改为"超期自动签离" */ @Scheduled(cron = "59 59 23 * * ?") @Transactional(rollbackFor = Exception.class) public void processOverdueAutoSignOut() { log.info("========== 开始处理超期自动签离定时任务 =========="); long startTime = System.currentTimeMillis(); try { // 获取当前时间(23:59:59) Date now = new Date(); // 获取今天的开始时间(00:00:00) Date todayStart = getTodayStartTime(); // 获取今天的结束时间(23:59:59) Date todayEnd = getTodayEndTime(); log.info("执行时间:{}", DateUtil.format(now, "yyyy-MM-dd HH:mm:ss")); log.info("查询范围:有效期结束时间在 {} 到 {} 之间", DateUtil.format(todayStart, "yyyy-MM-dd HH:mm:ss"), DateUtil.format(todayEnd, "yyyy-MM-dd HH:mm:ss")); // 1. 查询当天到期的记录(有效期结束时间在当天,且未签离) // 查询所有超过有效期且未签离的记录 // 条件:valid_end_time < 当前时间(即已经过了有效期) LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.lt(SysVisitorRecord::getValidEndTime, now) // 有效期结束时间 < 当前时间(已过期) .in(SysVisitorRecord::getStatus, Arrays.asList("VISITING", "PENDING_CONFIRM")) // 只处理未签离的状态 .eq(SysVisitorRecord::getDelFlag, "0") .isNull(SysVisitorRecord::getSignTime); // 确保还没有签离时间(防止重复处理) List overdueRecords = visitorRecordMapper.selectList(wrapper); if (overdueRecords == null || overdueRecords.isEmpty()) { log.info("没有需要处理的超期记录"); return; } log.info("查询到需要自动签离的记录数:{}", overdueRecords.size()); int successCount = 0; int failCount = 0; // 2. 逐条处理超期记录 for (SysVisitorRecord record : overdueRecords) { try { // 检查是否已经有签离时间(防止重复处理) if (record.getSignTime() != null) { log.warn("记录已有签离时间,跳过处理,recordId: {}, signTime: {}", record.getRecordId(), record.getSignTime()); continue; } // 更新记录状态为超期自动签离 LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(SysVisitorRecord::getRecordId, record.getRecordId()) .set(SysVisitorRecord::getStatus, "OVERDUE_AUTO_SIGNED_OUT") .set(SysVisitorRecord::getSignTime, new Date()) // 签离时间设为有效期结束时间 .set(SysVisitorRecord::getSignReceiverName, "系统自动") .set(SysVisitorRecord::getSignVerifyMethod, "AUTO") .set(SysVisitorRecord::getSignImageUrl, null) .set(SysVisitorRecord::getUpdateTime, new Date()) .set(SysVisitorRecord::getRemark, (record.getRemark() != null ? record.getRemark() + ";" : "") + "超期自动签离(有效期至:" + DateUtil.format(record.getValidEndTime(), "yyyy-MM-dd HH:mm:ss") + ")"); int updateCount = visitorRecordMapper.update(null, updateWrapper); if (updateCount > 0) { successCount++; log.info("超期自动签离成功,recordId: {}, 姓名: {}, 身份证号: {}, 有效期结束时间: {}", record.getRecordId(), record.getVisitorName(), record.getIdCard(), DateUtil.format(record.getValidEndTime(), "yyyy-MM-dd HH:mm:ss")); } else { failCount++; log.error("超期自动签离失败,recordId: {}", record.getRecordId()); } } catch (Exception e) { failCount++; log.error("处理超期自动签离异常,recordId: {}", record.getRecordId(), e); } } long endTime = System.currentTimeMillis(); log.info("========== 超期自动签离定时任务完成 =========="); log.info("总记录数:{},成功:{},失败:{},耗时:{}ms", overdueRecords.size(), successCount, failCount, (endTime - startTime)); } catch (Exception e) { log.error("超期自动签离定时任务执行异常", e); } } /** * 获取今天的开始时间(00:00:00) */ private Date getTodayStartTime() { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } /** * 获取今天的结束时间(23:59:59) */ private Date getTodayEndTime() { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.set(Calendar.HOUR_OF_DAY, 23); calendar.set(Calendar.MINUTE, 59); calendar.set(Calendar.SECOND, 59); calendar.set(Calendar.MILLISECOND, 999); return calendar.getTime(); } }